From 1795caf5d3d1b6ae03dcf6436a2f26047e1823cd Mon Sep 17 00:00:00 2001 From: notmike Date: Tue, 3 Feb 2026 00:10:02 -0700 Subject: [PATCH 1/7] remove dilitihium/ and sphincsplus/ copies --- dilithium/.gitignore | 9 - dilithium/.travis.yml | 33 - dilithium/AUTHORS.md | 7 - dilithium/Common_META.yml | 15 - dilithium/Dilithium2_META.yml | 44 - dilithium/Dilithium3_META.yml | 44 - dilithium/Dilithium5_META.yml | 44 - dilithium/LICENSE | 7 - dilithium/README.md | 81 -- dilithium/SHA256SUMS | 3 - dilithium/avx2/.gitignore | 2 - dilithium/avx2/Makefile | 118 -- dilithium/avx2/align.h | 19 - dilithium/avx2/api.h | 100 -- dilithium/avx2/config.h | 27 - dilithium/avx2/consts.c | 100 -- dilithium/avx2/consts.h | 38 - dilithium/avx2/f1600x4.S | 909 ------------- dilithium/avx2/fips202.c | 1 - dilithium/avx2/fips202.h | 57 - dilithium/avx2/fips202x4.c | 196 --- dilithium/avx2/fips202x4.h | 91 -- dilithium/avx2/invntt.S | 240 ---- dilithium/avx2/ntt.S | 198 --- dilithium/avx2/ntt.h | 19 - dilithium/avx2/packing.c | 1 - dilithium/avx2/packing.h | 1 - dilithium/avx2/params.h | 1 - dilithium/avx2/pointwise.S | 213 ---- dilithium/avx2/poly.c | 1128 ----------------- dilithium/avx2/poly.h | 112 -- dilithium/avx2/polyvec.c | 588 --------- dilithium/avx2/polyvec.h | 105 -- dilithium/avx2/randombytes.c | 1 - dilithium/avx2/randombytes.h | 1 - dilithium/avx2/rejsample.c | 476 ------- dilithium/avx2/rejsample.h | 28 - dilithium/avx2/rounding.c | 200 --- dilithium/avx2/rounding.h | 17 - dilithium/avx2/shuffle.S | 54 - dilithium/avx2/shuffle.inc | 25 - dilithium/avx2/sign.c | 530 -------- dilithium/avx2/sign.h | 1 - dilithium/avx2/symmetric-shake.c | 1 - dilithium/avx2/symmetric.h | 26 - dilithium/avx2/test/.gitignore | 10 - dilithium/avx2/test/cpucycles.c | 1 - dilithium/avx2/test/cpucycles.h | 1 - dilithium/avx2/test/speed_print.c | 1 - dilithium/avx2/test/speed_print.h | 1 - dilithium/avx2/test/test_dilithium.c | 1 - dilithium/avx2/test/test_mul.c | 1 - dilithium/avx2/test/test_speed.c | 1 - dilithium/avx2/test/test_vectors.c | 275 ---- dilithium/ref/.gitignore | 2 - dilithium/ref/Makefile | 139 -- dilithium/ref/api.h | 98 -- dilithium/ref/config.h | 27 - dilithium/ref/fips202.c | 774 ----------- dilithium/ref/fips202.h | 57 - dilithium/ref/nistkat/.gitignore | 3 - dilithium/ref/nistkat/PQCgenKAT_sign.c | 261 ---- dilithium/ref/nistkat/rng.c | 222 ---- dilithium/ref/nistkat/rng.h | 55 - dilithium/ref/ntt.c | 98 -- dilithium/ref/ntt.h | 13 - dilithium/ref/packing.c | 237 ---- dilithium/ref/packing.h | 38 - dilithium/ref/params.h | 80 -- dilithium/ref/poly.c | 907 ------------- dilithium/ref/poly.h | 79 -- dilithium/ref/polyvec.c | 389 ------ dilithium/ref/polyvec.h | 93 -- dilithium/ref/precomp.gp | 12 - dilithium/ref/randombytes.c | 80 -- dilithium/ref/randombytes.h | 9 - dilithium/ref/randombytes_custom.c | 12 - dilithium/ref/reduce.c | 69 - dilithium/ref/reduce.h | 22 - dilithium/ref/rounding.c | 102 -- dilithium/ref/rounding.h | 19 - dilithium/ref/sign.c | 443 ------- dilithium/ref/sign.h | 56 - dilithium/ref/symmetric-shake.c | 28 - dilithium/ref/symmetric.h | 34 - dilithium/ref/test/.gitignore | 10 - dilithium/ref/test/cpucycles.c | 17 - dilithium/ref/test/cpucycles.h | 33 - dilithium/ref/test/speed_print.c | 51 - dilithium/ref/test/speed_print.h | 9 - dilithium/ref/test/test_dilithium.c | 69 - dilithium/ref/test/test_mul.c | 60 - dilithium/ref/test/test_speed.c | 87 -- dilithium/ref/test/test_vectors.c | 251 ---- dilithium/runlcov.sh | 21 - dilithium/runtests.sh | 33 - .../.github/workflows/test-haraka-aesni.yml | 33 - sphincsplus/.github/workflows/test-ref.yml | 37 - .../.github/workflows/test-sha2-avx2.yml | 33 - .../.github/workflows/test-shake-avx2.yml | 33 - sphincsplus/.reuse/dep5 | 15 - sphincsplus/LICENSE | 2 - sphincsplus/LICENSES/0BSD.txt | 12 - sphincsplus/LICENSES/CC0-1.0.txt | 122 -- .../LicenseRef-SPHINCS-PLUS-Public-Domain.txt | 2 - sphincsplus/LICENSES/MIT-0.txt | 15 - sphincsplus/LICENSES/MIT.txt | 8 - sphincsplus/README.md | 37 - sphincsplus/SHA256SUMS | 36 - sphincsplus/benchmark.py | 39 - sphincsplus/haraka-aesni/.gitignore | 5 - sphincsplus/haraka-aesni/Makefile | 47 - sphincsplus/haraka-aesni/PQCgenKAT_sign.c | 1 - sphincsplus/haraka-aesni/address.c | 1 - sphincsplus/haraka-aesni/address.h | 1 - sphincsplus/haraka-aesni/api.h | 1 - sphincsplus/haraka-aesni/context.h | 16 - sphincsplus/haraka-aesni/fors.c | 1 - sphincsplus/haraka-aesni/fors.h | 1 - sphincsplus/haraka-aesni/haraka.c | 720 ----------- sphincsplus/haraka-aesni/haraka.h | 1 - sphincsplus/haraka-aesni/haraka_offsets.h | 1 - sphincsplus/haraka-aesni/harakax4.h | 36 - sphincsplus/haraka-aesni/hash.h | 1 - sphincsplus/haraka-aesni/hash_haraka.c | 1 - sphincsplus/haraka-aesni/hash_harakax4.c | 36 - sphincsplus/haraka-aesni/hashx4.h | 1 - sphincsplus/haraka-aesni/merkle.c | 1 - sphincsplus/haraka-aesni/merkle.h | 1 - sphincsplus/haraka-aesni/params.h | 1 - .../params/params-sphincs-haraka-128f.h | 1 - .../params/params-sphincs-haraka-128s.h | 1 - .../params/params-sphincs-haraka-192f.h | 1 - .../params/params-sphincs-haraka-192s.h | 1 - .../params/params-sphincs-haraka-256f.h | 1 - .../params/params-sphincs-haraka-256s.h | 1 - sphincsplus/haraka-aesni/randombytes.c | 1 - sphincsplus/haraka-aesni/randombytes.h | 1 - sphincsplus/haraka-aesni/rng.c | 1 - sphincsplus/haraka-aesni/rng.h | 1 - sphincsplus/haraka-aesni/sign.c | 1 - sphincsplus/haraka-aesni/test/benchmark.c | 162 --- sphincsplus/haraka-aesni/test/fors.c | 1 - sphincsplus/haraka-aesni/test/spx.c | 1 - sphincsplus/haraka-aesni/thash.h | 1 - .../haraka-aesni/thash_haraka_robust.c | 1 - .../haraka-aesni/thash_haraka_robustx4.c | 93 -- .../haraka-aesni/thash_haraka_simple.c | 1 - .../haraka-aesni/thash_haraka_simplex4.c | 67 - sphincsplus/haraka-aesni/thashx4.h | 1 - sphincsplus/haraka-aesni/utils.c | 1 - sphincsplus/haraka-aesni/utils.h | 1 - sphincsplus/haraka-aesni/utilsx4.c | 1 - sphincsplus/haraka-aesni/utilsx4.h | 1 - sphincsplus/haraka-aesni/wots.c | 1 - sphincsplus/haraka-aesni/wots.h | 1 - sphincsplus/haraka-aesni/wotsx4.h | 1 - sphincsplus/ref/.gitignore | 5 - sphincsplus/ref/Makefile | 65 - sphincsplus/ref/PQCgenKAT_sign.c | 262 ---- sphincsplus/ref/address.c | 104 -- sphincsplus/ref/address.h | 51 - sphincsplus/ref/api.h | 77 -- sphincsplus/ref/context.h | 28 - sphincsplus/ref/fips202.c | 598 --------- sphincsplus/ref/fips202.h | 47 - sphincsplus/ref/fors.c | 161 --- sphincsplus/ref/fors.h | 32 - sphincsplus/ref/haraka.c | 965 -------------- sphincsplus/ref/haraka.h | 41 - sphincsplus/ref/haraka_offsets.h | 20 - sphincsplus/ref/hash.h | 27 - sphincsplus/ref/hash_haraka.c | 96 -- sphincsplus/ref/hash_sha2.c | 197 --- sphincsplus/ref/hash_shake.c | 97 -- sphincsplus/ref/merkle.c | 61 - sphincsplus/ref/merkle.h | 18 - sphincsplus/ref/params.h | 5 - .../ref/params/params-sphincs-haraka-128f.h | 80 -- .../ref/params/params-sphincs-haraka-128s.h | 80 -- .../ref/params/params-sphincs-haraka-192f.h | 80 -- .../ref/params/params-sphincs-haraka-192s.h | 80 -- .../ref/params/params-sphincs-haraka-256f.h | 80 -- .../ref/params/params-sphincs-haraka-256s.h | 80 -- .../ref/params/params-sphincs-sha2-128f.h | 85 -- .../ref/params/params-sphincs-sha2-128s.h | 85 -- .../ref/params/params-sphincs-sha2-192f.h | 85 -- .../ref/params/params-sphincs-sha2-192s.h | 85 -- .../ref/params/params-sphincs-sha2-256f.h | 85 -- .../ref/params/params-sphincs-sha2-256s.h | 85 -- .../ref/params/params-sphincs-shake-128f.h | 80 -- .../ref/params/params-sphincs-shake-128s.h | 80 -- .../ref/params/params-sphincs-shake-192f.h | 80 -- .../ref/params/params-sphincs-shake-192s.h | 80 -- .../ref/params/params-sphincs-shake-256f.h | 80 -- .../ref/params/params-sphincs-shake-256s.h | 80 -- sphincsplus/ref/randombytes.c | 43 - sphincsplus/ref/randombytes.h | 6 - sphincsplus/ref/randombytes_custom.c | 12 - sphincsplus/ref/rng.c | 218 ---- sphincsplus/ref/rng.h | 54 - sphincsplus/ref/sha2.c | 700 ---------- sphincsplus/ref/sha2.h | 43 - sphincsplus/ref/sha2_offsets.h | 20 - sphincsplus/ref/shake_offsets.h | 20 - sphincsplus/ref/sign.c | 287 ----- sphincsplus/ref/test/benchmark.c | 173 --- sphincsplus/ref/test/cycles.c | 110 -- sphincsplus/ref/test/fors.c | 41 - sphincsplus/ref/test/haraka.c | 155 --- sphincsplus/ref/test/spx.c | 125 -- sphincsplus/ref/thash.h | 13 - sphincsplus/ref/thash_haraka_robust.c | 46 - sphincsplus/ref/thash_haraka_simple.c | 37 - sphincsplus/ref/thash_sha2_robust.c | 74 -- sphincsplus/ref/thash_sha2_simple.c | 59 - sphincsplus/ref/thash_shake_robust.c | 31 - sphincsplus/ref/thash_shake_simple.c | 24 - sphincsplus/ref/utils.c | 154 --- sphincsplus/ref/utils.h | 64 - sphincsplus/ref/utilsx1.c | 100 -- sphincsplus/ref/utilsx1.h | 26 - sphincsplus/ref/wots.c | 112 -- sphincsplus/ref/wots.h | 25 - sphincsplus/ref/wotsx1.c | 73 -- sphincsplus/ref/wotsx1.h | 36 - sphincsplus/sha2-avx2/.gitignore | 6 - sphincsplus/sha2-avx2/Makefile | 48 - sphincsplus/sha2-avx2/PQCgenKAT_sign.c | 1 - sphincsplus/sha2-avx2/address.c | 1 - sphincsplus/sha2-avx2/address.h | 1 - sphincsplus/sha2-avx2/api.h | 1 - sphincsplus/sha2-avx2/context.h | 18 - sphincsplus/sha2-avx2/fors.c | 233 ---- sphincsplus/sha2-avx2/fors.h | 1 - sphincsplus/sha2-avx2/hash.h | 1 - sphincsplus/sha2-avx2/hash_sha2.c | 1 - sphincsplus/sha2-avx2/hash_sha2x8.c | 74 -- sphincsplus/sha2-avx2/hashx8.h | 19 - sphincsplus/sha2-avx2/merkle.c | 67 - sphincsplus/sha2-avx2/merkle.h | 1 - sphincsplus/sha2-avx2/params.h | 1 - .../params/params-sphincs-sha2-128f.h | 1 - .../params/params-sphincs-sha2-128s.h | 1 - .../params/params-sphincs-sha2-192f.h | 1 - .../params/params-sphincs-sha2-192s.h | 1 - .../params/params-sphincs-sha2-256f.h | 1 - .../params/params-sphincs-sha2-256s.h | 1 - sphincsplus/sha2-avx2/randombytes.c | 1 - sphincsplus/sha2-avx2/randombytes.h | 1 - sphincsplus/sha2-avx2/rng.c | 1 - sphincsplus/sha2-avx2/rng.h | 1 - sphincsplus/sha2-avx2/sha2.c | 1 - sphincsplus/sha2-avx2/sha2.h | 1 - sphincsplus/sha2-avx2/sha256avx.c | 294 ----- sphincsplus/sha2-avx2/sha256avx.h | 96 -- sphincsplus/sha2-avx2/sha256x8.c | 201 --- sphincsplus/sha2-avx2/sha256x8.h | 69 - sphincsplus/sha2-avx2/sha2_offsets.h | 1 - sphincsplus/sha2-avx2/sha512x4.c | 462 ------- sphincsplus/sha2-avx2/sha512x4.h | 44 - sphincsplus/sha2-avx2/sign.c | 1 - sphincsplus/sha2-avx2/test/benchmark.c | 162 --- sphincsplus/sha2-avx2/test/fors.c | 1 - sphincsplus/sha2-avx2/test/spx.c | 1 - sphincsplus/sha2-avx2/test/thashx8.c | 94 -- sphincsplus/sha2-avx2/thash.h | 1 - sphincsplus/sha2-avx2/thash_sha2_robust.c | 1 - sphincsplus/sha2-avx2/thash_sha2_robustx8.c | 276 ---- sphincsplus/sha2-avx2/thash_sha2_simple.c | 1 - sphincsplus/sha2-avx2/thash_sha2_simplex8.c | 220 ---- sphincsplus/sha2-avx2/thashx8.h | 27 - sphincsplus/sha2-avx2/utils.c | 1 - sphincsplus/sha2-avx2/utils.h | 1 - sphincsplus/sha2-avx2/utilsx8.c | 146 --- sphincsplus/sha2-avx2/utilsx8.h | 28 - sphincsplus/sha2-avx2/wots.c | 293 ----- sphincsplus/sha2-avx2/wots.h | 1 - sphincsplus/sha2-avx2/wotsx8.h | 40 - sphincsplus/shake-a64/.gitignore | 5 - sphincsplus/shake-a64/Makefile | 49 - sphincsplus/shake-a64/PQCgenKAT_sign.c | 1 - sphincsplus/shake-a64/address.c | 1 - sphincsplus/shake-a64/address.h | 1 - sphincsplus/shake-a64/api.h | 1 - sphincsplus/shake-a64/context.h | 13 - sphincsplus/shake-a64/f1600x2.h | 11 - sphincsplus/shake-a64/f1600x2.s | 143 --- sphincsplus/shake-a64/f1600x2_const.c | 30 - sphincsplus/shake-a64/fips202.c | 1 - sphincsplus/shake-a64/fips202.h | 1 - sphincsplus/shake-a64/fips202x2.c | 165 --- sphincsplus/shake-a64/fips202x2.h | 24 - sphincsplus/shake-a64/fors.c | 198 --- sphincsplus/shake-a64/fors.h | 1 - sphincsplus/shake-a64/hash.h | 1 - sphincsplus/shake-a64/hash_shake.c | 1 - sphincsplus/shake-a64/hash_shakex2.c | 51 - sphincsplus/shake-a64/hashx2.h | 14 - sphincsplus/shake-a64/merkle.c | 65 - sphincsplus/shake-a64/merkle.h | 1 - sphincsplus/shake-a64/params.h | 1 - .../params/params-sphincs-shake-128f.h | 1 - .../params/params-sphincs-shake-128s.h | 1 - .../params/params-sphincs-shake-192f.h | 1 - .../params/params-sphincs-shake-192s.h | 1 - .../params/params-sphincs-shake-256f.h | 1 - .../params/params-sphincs-shake-256s.h | 1 - sphincsplus/shake-a64/randombytes.c | 1 - sphincsplus/shake-a64/randombytes.h | 1 - sphincsplus/shake-a64/rng.c | 1 - sphincsplus/shake-a64/rng.h | 1 - sphincsplus/shake-a64/shake_offsets.h | 1 - sphincsplus/shake-a64/sign.c | 1 - sphincsplus/shake-a64/test/benchmark.c | 175 --- sphincsplus/shake-a64/test/cycles.c | 1 - sphincsplus/shake-a64/test/fors.c | 1 - sphincsplus/shake-a64/test/spx.c | 1 - sphincsplus/shake-a64/test/thashx2.c | 43 - sphincsplus/shake-a64/thash.h | 12 - sphincsplus/shake-a64/thash_shake_robustx2.c | 112 -- sphincsplus/shake-a64/thash_shake_simplex2.c | 83 -- sphincsplus/shake-a64/thashx2.h | 16 - sphincsplus/shake-a64/utils.c | 1 - sphincsplus/shake-a64/utils.h | 1 - sphincsplus/shake-a64/utilsx2.c | 130 -- sphincsplus/shake-a64/utilsx2.h | 28 - sphincsplus/shake-a64/wots.c | 261 ---- sphincsplus/shake-a64/wots.h | 1 - sphincsplus/shake-a64/wotsx2.h | 40 - sphincsplus/shake-avx2/.gitignore | 6 - sphincsplus/shake-avx2/Makefile | 56 - sphincsplus/shake-avx2/PQCgenKAT_sign.c | 1 - sphincsplus/shake-avx2/address.c | 1 - sphincsplus/shake-avx2/address.h | 1 - sphincsplus/shake-avx2/api.h | 1 - sphincsplus/shake-avx2/context.h | 13 - sphincsplus/shake-avx2/fips202.c | 1 - sphincsplus/shake-avx2/fips202.h | 1 - sphincsplus/shake-avx2/fips202x4.c | 225 ---- sphincsplus/shake-avx2/fips202x4.h | 24 - sphincsplus/shake-avx2/fors.c | 209 --- sphincsplus/shake-avx2/fors.h | 1 - sphincsplus/shake-avx2/hash.h | 1 - sphincsplus/shake-avx2/hash_shake.c | 1 - sphincsplus/shake-avx2/hash_shakex4.c | 63 - sphincsplus/shake-avx2/hashx4.h | 16 - .../keccak4x/KeccakP-1600-times4-SIMD256.c | 1030 --------------- .../keccak4x/KeccakP-1600-times4-SnP.h | 50 - .../keccak4x/KeccakP-1600-unrolling.macros | 198 --- .../shake-avx2/keccak4x/SIMD256-config.h | 3 - sphincsplus/shake-avx2/keccak4x/align.h | 34 - sphincsplus/shake-avx2/keccak4x/brg_endian.h | 142 --- sphincsplus/shake-avx2/merkle.c | 65 - sphincsplus/shake-avx2/merkle.h | 1 - sphincsplus/shake-avx2/params.h | 1 - .../params/params-sphincs-shake-128f.h | 1 - .../params/params-sphincs-shake-128s.h | 1 - .../params/params-sphincs-shake-192f.h | 1 - .../params/params-sphincs-shake-192s.h | 1 - .../params/params-sphincs-shake-256f.h | 1 - .../params/params-sphincs-shake-256s.h | 1 - sphincsplus/shake-avx2/randombytes.c | 1 - sphincsplus/shake-avx2/randombytes.h | 1 - sphincsplus/shake-avx2/rng.c | 1 - sphincsplus/shake-avx2/rng.h | 1 - sphincsplus/shake-avx2/shake_offsets.h | 1 - sphincsplus/shake-avx2/sign.c | 1 - sphincsplus/shake-avx2/test/benchmark.c | 161 --- sphincsplus/shake-avx2/test/fors.c | 1 - sphincsplus/shake-avx2/test/spx.c | 1 - sphincsplus/shake-avx2/test/thashx4.c | 47 - sphincsplus/shake-avx2/thash.h | 1 - sphincsplus/shake-avx2/thash_shake_robust.c | 1 - sphincsplus/shake-avx2/thash_shake_robustx4.c | 131 -- sphincsplus/shake-avx2/thash_shake_simple.c | 1 - sphincsplus/shake-avx2/thash_shake_simplex4.c | 98 -- sphincsplus/shake-avx2/thashx4.h | 19 - sphincsplus/shake-avx2/utils.c | 1 - sphincsplus/shake-avx2/utils.h | 1 - sphincsplus/shake-avx2/utilsx4.c | 138 -- sphincsplus/shake-avx2/utilsx4.h | 28 - sphincsplus/shake-avx2/wots.c | 271 ---- sphincsplus/shake-avx2/wots.h | 1 - sphincsplus/shake-avx2/wotsx4.h | 40 - sphincsplus/vectors.py | 101 -- 386 files changed, 28098 deletions(-) delete mode 100644 dilithium/.gitignore delete mode 100644 dilithium/.travis.yml delete mode 100644 dilithium/AUTHORS.md delete mode 100644 dilithium/Common_META.yml delete mode 100644 dilithium/Dilithium2_META.yml delete mode 100644 dilithium/Dilithium3_META.yml delete mode 100644 dilithium/Dilithium5_META.yml delete mode 100644 dilithium/LICENSE delete mode 100644 dilithium/README.md delete mode 100644 dilithium/SHA256SUMS delete mode 100644 dilithium/avx2/.gitignore delete mode 100644 dilithium/avx2/Makefile delete mode 100644 dilithium/avx2/align.h delete mode 100644 dilithium/avx2/api.h delete mode 100644 dilithium/avx2/config.h delete mode 100644 dilithium/avx2/consts.c delete mode 100644 dilithium/avx2/consts.h delete mode 100644 dilithium/avx2/f1600x4.S delete mode 120000 dilithium/avx2/fips202.c delete mode 100644 dilithium/avx2/fips202.h delete mode 100644 dilithium/avx2/fips202x4.c delete mode 100644 dilithium/avx2/fips202x4.h delete mode 100644 dilithium/avx2/invntt.S delete mode 100644 dilithium/avx2/ntt.S delete mode 100644 dilithium/avx2/ntt.h delete mode 120000 dilithium/avx2/packing.c delete mode 120000 dilithium/avx2/packing.h delete mode 120000 dilithium/avx2/params.h delete mode 100644 dilithium/avx2/pointwise.S delete mode 100644 dilithium/avx2/poly.c delete mode 100644 dilithium/avx2/poly.h delete mode 100644 dilithium/avx2/polyvec.c delete mode 100644 dilithium/avx2/polyvec.h delete mode 120000 dilithium/avx2/randombytes.c delete mode 120000 dilithium/avx2/randombytes.h delete mode 100644 dilithium/avx2/rejsample.c delete mode 100644 dilithium/avx2/rejsample.h delete mode 100644 dilithium/avx2/rounding.c delete mode 100644 dilithium/avx2/rounding.h delete mode 100644 dilithium/avx2/shuffle.S delete mode 100644 dilithium/avx2/shuffle.inc delete mode 100644 dilithium/avx2/sign.c delete mode 120000 dilithium/avx2/sign.h delete mode 120000 dilithium/avx2/symmetric-shake.c delete mode 100644 dilithium/avx2/symmetric.h delete mode 100644 dilithium/avx2/test/.gitignore delete mode 120000 dilithium/avx2/test/cpucycles.c delete mode 120000 dilithium/avx2/test/cpucycles.h delete mode 120000 dilithium/avx2/test/speed_print.c delete mode 120000 dilithium/avx2/test/speed_print.h delete mode 120000 dilithium/avx2/test/test_dilithium.c delete mode 120000 dilithium/avx2/test/test_mul.c delete mode 120000 dilithium/avx2/test/test_speed.c delete mode 100644 dilithium/avx2/test/test_vectors.c delete mode 100644 dilithium/ref/.gitignore delete mode 100644 dilithium/ref/Makefile delete mode 100644 dilithium/ref/api.h delete mode 100644 dilithium/ref/config.h delete mode 100644 dilithium/ref/fips202.c delete mode 100644 dilithium/ref/fips202.h delete mode 100644 dilithium/ref/nistkat/.gitignore delete mode 100644 dilithium/ref/nistkat/PQCgenKAT_sign.c delete mode 100644 dilithium/ref/nistkat/rng.c delete mode 100644 dilithium/ref/nistkat/rng.h delete mode 100644 dilithium/ref/ntt.c delete mode 100644 dilithium/ref/ntt.h delete mode 100644 dilithium/ref/packing.c delete mode 100644 dilithium/ref/packing.h delete mode 100644 dilithium/ref/params.h delete mode 100644 dilithium/ref/poly.c delete mode 100644 dilithium/ref/poly.h delete mode 100644 dilithium/ref/polyvec.c delete mode 100644 dilithium/ref/polyvec.h delete mode 100644 dilithium/ref/precomp.gp delete mode 100644 dilithium/ref/randombytes.c delete mode 100644 dilithium/ref/randombytes.h delete mode 100644 dilithium/ref/randombytes_custom.c delete mode 100644 dilithium/ref/reduce.c delete mode 100644 dilithium/ref/reduce.h delete mode 100644 dilithium/ref/rounding.c delete mode 100644 dilithium/ref/rounding.h delete mode 100644 dilithium/ref/sign.c delete mode 100644 dilithium/ref/sign.h delete mode 100644 dilithium/ref/symmetric-shake.c delete mode 100644 dilithium/ref/symmetric.h delete mode 100644 dilithium/ref/test/.gitignore delete mode 100644 dilithium/ref/test/cpucycles.c delete mode 100644 dilithium/ref/test/cpucycles.h delete mode 100644 dilithium/ref/test/speed_print.c delete mode 100644 dilithium/ref/test/speed_print.h delete mode 100644 dilithium/ref/test/test_dilithium.c delete mode 100644 dilithium/ref/test/test_mul.c delete mode 100644 dilithium/ref/test/test_speed.c delete mode 100644 dilithium/ref/test/test_vectors.c delete mode 100755 dilithium/runlcov.sh delete mode 100755 dilithium/runtests.sh delete mode 100644 sphincsplus/.github/workflows/test-haraka-aesni.yml delete mode 100644 sphincsplus/.github/workflows/test-ref.yml delete mode 100644 sphincsplus/.github/workflows/test-sha2-avx2.yml delete mode 100644 sphincsplus/.github/workflows/test-shake-avx2.yml delete mode 100644 sphincsplus/.reuse/dep5 delete mode 100644 sphincsplus/LICENSE delete mode 100644 sphincsplus/LICENSES/0BSD.txt delete mode 100644 sphincsplus/LICENSES/CC0-1.0.txt delete mode 100644 sphincsplus/LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt delete mode 100644 sphincsplus/LICENSES/MIT-0.txt delete mode 100644 sphincsplus/LICENSES/MIT.txt delete mode 100644 sphincsplus/README.md delete mode 100644 sphincsplus/SHA256SUMS delete mode 100755 sphincsplus/benchmark.py delete mode 100644 sphincsplus/haraka-aesni/.gitignore delete mode 100644 sphincsplus/haraka-aesni/Makefile delete mode 120000 sphincsplus/haraka-aesni/PQCgenKAT_sign.c delete mode 120000 sphincsplus/haraka-aesni/address.c delete mode 120000 sphincsplus/haraka-aesni/address.h delete mode 120000 sphincsplus/haraka-aesni/api.h delete mode 100644 sphincsplus/haraka-aesni/context.h delete mode 120000 sphincsplus/haraka-aesni/fors.c delete mode 120000 sphincsplus/haraka-aesni/fors.h delete mode 100644 sphincsplus/haraka-aesni/haraka.c delete mode 120000 sphincsplus/haraka-aesni/haraka.h delete mode 120000 sphincsplus/haraka-aesni/haraka_offsets.h delete mode 100644 sphincsplus/haraka-aesni/harakax4.h delete mode 120000 sphincsplus/haraka-aesni/hash.h delete mode 120000 sphincsplus/haraka-aesni/hash_haraka.c delete mode 100644 sphincsplus/haraka-aesni/hash_harakax4.c delete mode 120000 sphincsplus/haraka-aesni/hashx4.h delete mode 120000 sphincsplus/haraka-aesni/merkle.c delete mode 120000 sphincsplus/haraka-aesni/merkle.h delete mode 120000 sphincsplus/haraka-aesni/params.h delete mode 120000 sphincsplus/haraka-aesni/params/params-sphincs-haraka-128f.h delete mode 120000 sphincsplus/haraka-aesni/params/params-sphincs-haraka-128s.h delete mode 120000 sphincsplus/haraka-aesni/params/params-sphincs-haraka-192f.h delete mode 120000 sphincsplus/haraka-aesni/params/params-sphincs-haraka-192s.h delete mode 120000 sphincsplus/haraka-aesni/params/params-sphincs-haraka-256f.h delete mode 120000 sphincsplus/haraka-aesni/params/params-sphincs-haraka-256s.h delete mode 120000 sphincsplus/haraka-aesni/randombytes.c delete mode 120000 sphincsplus/haraka-aesni/randombytes.h delete mode 120000 sphincsplus/haraka-aesni/rng.c delete mode 120000 sphincsplus/haraka-aesni/rng.h delete mode 120000 sphincsplus/haraka-aesni/sign.c delete mode 100644 sphincsplus/haraka-aesni/test/benchmark.c delete mode 120000 sphincsplus/haraka-aesni/test/fors.c delete mode 120000 sphincsplus/haraka-aesni/test/spx.c delete mode 120000 sphincsplus/haraka-aesni/thash.h delete mode 120000 sphincsplus/haraka-aesni/thash_haraka_robust.c delete mode 100644 sphincsplus/haraka-aesni/thash_haraka_robustx4.c delete mode 120000 sphincsplus/haraka-aesni/thash_haraka_simple.c delete mode 100644 sphincsplus/haraka-aesni/thash_haraka_simplex4.c delete mode 120000 sphincsplus/haraka-aesni/thashx4.h delete mode 120000 sphincsplus/haraka-aesni/utils.c delete mode 120000 sphincsplus/haraka-aesni/utils.h delete mode 120000 sphincsplus/haraka-aesni/utilsx4.c delete mode 120000 sphincsplus/haraka-aesni/utilsx4.h delete mode 120000 sphincsplus/haraka-aesni/wots.c delete mode 120000 sphincsplus/haraka-aesni/wots.h delete mode 120000 sphincsplus/haraka-aesni/wotsx4.h delete mode 100644 sphincsplus/ref/.gitignore delete mode 100644 sphincsplus/ref/Makefile delete mode 100644 sphincsplus/ref/PQCgenKAT_sign.c delete mode 100644 sphincsplus/ref/address.c delete mode 100644 sphincsplus/ref/address.h delete mode 100644 sphincsplus/ref/api.h delete mode 100644 sphincsplus/ref/context.h delete mode 100644 sphincsplus/ref/fips202.c delete mode 100644 sphincsplus/ref/fips202.h delete mode 100644 sphincsplus/ref/fors.c delete mode 100644 sphincsplus/ref/fors.h delete mode 100644 sphincsplus/ref/haraka.c delete mode 100644 sphincsplus/ref/haraka.h delete mode 100644 sphincsplus/ref/haraka_offsets.h delete mode 100644 sphincsplus/ref/hash.h delete mode 100644 sphincsplus/ref/hash_haraka.c delete mode 100644 sphincsplus/ref/hash_sha2.c delete mode 100644 sphincsplus/ref/hash_shake.c delete mode 100644 sphincsplus/ref/merkle.c delete mode 100644 sphincsplus/ref/merkle.h delete mode 100644 sphincsplus/ref/params.h delete mode 100644 sphincsplus/ref/params/params-sphincs-haraka-128f.h delete mode 100644 sphincsplus/ref/params/params-sphincs-haraka-128s.h delete mode 100644 sphincsplus/ref/params/params-sphincs-haraka-192f.h delete mode 100644 sphincsplus/ref/params/params-sphincs-haraka-192s.h delete mode 100644 sphincsplus/ref/params/params-sphincs-haraka-256f.h delete mode 100644 sphincsplus/ref/params/params-sphincs-haraka-256s.h delete mode 100644 sphincsplus/ref/params/params-sphincs-sha2-128f.h delete mode 100644 sphincsplus/ref/params/params-sphincs-sha2-128s.h delete mode 100644 sphincsplus/ref/params/params-sphincs-sha2-192f.h delete mode 100644 sphincsplus/ref/params/params-sphincs-sha2-192s.h delete mode 100644 sphincsplus/ref/params/params-sphincs-sha2-256f.h delete mode 100644 sphincsplus/ref/params/params-sphincs-sha2-256s.h delete mode 100644 sphincsplus/ref/params/params-sphincs-shake-128f.h delete mode 100644 sphincsplus/ref/params/params-sphincs-shake-128s.h delete mode 100644 sphincsplus/ref/params/params-sphincs-shake-192f.h delete mode 100644 sphincsplus/ref/params/params-sphincs-shake-192s.h delete mode 100644 sphincsplus/ref/params/params-sphincs-shake-256f.h delete mode 100644 sphincsplus/ref/params/params-sphincs-shake-256s.h delete mode 100644 sphincsplus/ref/randombytes.c delete mode 100644 sphincsplus/ref/randombytes.h delete mode 100644 sphincsplus/ref/randombytes_custom.c delete mode 100644 sphincsplus/ref/rng.c delete mode 100644 sphincsplus/ref/rng.h delete mode 100644 sphincsplus/ref/sha2.c delete mode 100644 sphincsplus/ref/sha2.h delete mode 100644 sphincsplus/ref/sha2_offsets.h delete mode 100644 sphincsplus/ref/shake_offsets.h delete mode 100644 sphincsplus/ref/sign.c delete mode 100644 sphincsplus/ref/test/benchmark.c delete mode 100644 sphincsplus/ref/test/cycles.c delete mode 100644 sphincsplus/ref/test/fors.c delete mode 100644 sphincsplus/ref/test/haraka.c delete mode 100644 sphincsplus/ref/test/spx.c delete mode 100644 sphincsplus/ref/thash.h delete mode 100644 sphincsplus/ref/thash_haraka_robust.c delete mode 100644 sphincsplus/ref/thash_haraka_simple.c delete mode 100644 sphincsplus/ref/thash_sha2_robust.c delete mode 100644 sphincsplus/ref/thash_sha2_simple.c delete mode 100644 sphincsplus/ref/thash_shake_robust.c delete mode 100644 sphincsplus/ref/thash_shake_simple.c delete mode 100644 sphincsplus/ref/utils.c delete mode 100644 sphincsplus/ref/utils.h delete mode 100644 sphincsplus/ref/utilsx1.c delete mode 100644 sphincsplus/ref/utilsx1.h delete mode 100644 sphincsplus/ref/wots.c delete mode 100644 sphincsplus/ref/wots.h delete mode 100644 sphincsplus/ref/wotsx1.c delete mode 100644 sphincsplus/ref/wotsx1.h delete mode 100644 sphincsplus/sha2-avx2/.gitignore delete mode 100644 sphincsplus/sha2-avx2/Makefile delete mode 120000 sphincsplus/sha2-avx2/PQCgenKAT_sign.c delete mode 120000 sphincsplus/sha2-avx2/address.c delete mode 120000 sphincsplus/sha2-avx2/address.h delete mode 120000 sphincsplus/sha2-avx2/api.h delete mode 100644 sphincsplus/sha2-avx2/context.h delete mode 100644 sphincsplus/sha2-avx2/fors.c delete mode 120000 sphincsplus/sha2-avx2/fors.h delete mode 120000 sphincsplus/sha2-avx2/hash.h delete mode 120000 sphincsplus/sha2-avx2/hash_sha2.c delete mode 100644 sphincsplus/sha2-avx2/hash_sha2x8.c delete mode 100644 sphincsplus/sha2-avx2/hashx8.h delete mode 100644 sphincsplus/sha2-avx2/merkle.c delete mode 120000 sphincsplus/sha2-avx2/merkle.h delete mode 120000 sphincsplus/sha2-avx2/params.h delete mode 120000 sphincsplus/sha2-avx2/params/params-sphincs-sha2-128f.h delete mode 120000 sphincsplus/sha2-avx2/params/params-sphincs-sha2-128s.h delete mode 120000 sphincsplus/sha2-avx2/params/params-sphincs-sha2-192f.h delete mode 120000 sphincsplus/sha2-avx2/params/params-sphincs-sha2-192s.h delete mode 120000 sphincsplus/sha2-avx2/params/params-sphincs-sha2-256f.h delete mode 120000 sphincsplus/sha2-avx2/params/params-sphincs-sha2-256s.h delete mode 120000 sphincsplus/sha2-avx2/randombytes.c delete mode 120000 sphincsplus/sha2-avx2/randombytes.h delete mode 120000 sphincsplus/sha2-avx2/rng.c delete mode 120000 sphincsplus/sha2-avx2/rng.h delete mode 120000 sphincsplus/sha2-avx2/sha2.c delete mode 120000 sphincsplus/sha2-avx2/sha2.h delete mode 100644 sphincsplus/sha2-avx2/sha256avx.c delete mode 100644 sphincsplus/sha2-avx2/sha256avx.h delete mode 100644 sphincsplus/sha2-avx2/sha256x8.c delete mode 100644 sphincsplus/sha2-avx2/sha256x8.h delete mode 120000 sphincsplus/sha2-avx2/sha2_offsets.h delete mode 100644 sphincsplus/sha2-avx2/sha512x4.c delete mode 100644 sphincsplus/sha2-avx2/sha512x4.h delete mode 120000 sphincsplus/sha2-avx2/sign.c delete mode 100644 sphincsplus/sha2-avx2/test/benchmark.c delete mode 120000 sphincsplus/sha2-avx2/test/fors.c delete mode 120000 sphincsplus/sha2-avx2/test/spx.c delete mode 100644 sphincsplus/sha2-avx2/test/thashx8.c delete mode 120000 sphincsplus/sha2-avx2/thash.h delete mode 120000 sphincsplus/sha2-avx2/thash_sha2_robust.c delete mode 100644 sphincsplus/sha2-avx2/thash_sha2_robustx8.c delete mode 120000 sphincsplus/sha2-avx2/thash_sha2_simple.c delete mode 100644 sphincsplus/sha2-avx2/thash_sha2_simplex8.c delete mode 100644 sphincsplus/sha2-avx2/thashx8.h delete mode 120000 sphincsplus/sha2-avx2/utils.c delete mode 120000 sphincsplus/sha2-avx2/utils.h delete mode 100644 sphincsplus/sha2-avx2/utilsx8.c delete mode 100644 sphincsplus/sha2-avx2/utilsx8.h delete mode 100644 sphincsplus/sha2-avx2/wots.c delete mode 120000 sphincsplus/sha2-avx2/wots.h delete mode 100644 sphincsplus/sha2-avx2/wotsx8.h delete mode 100644 sphincsplus/shake-a64/.gitignore delete mode 100644 sphincsplus/shake-a64/Makefile delete mode 120000 sphincsplus/shake-a64/PQCgenKAT_sign.c delete mode 120000 sphincsplus/shake-a64/address.c delete mode 120000 sphincsplus/shake-a64/address.h delete mode 120000 sphincsplus/shake-a64/api.h delete mode 100644 sphincsplus/shake-a64/context.h delete mode 100644 sphincsplus/shake-a64/f1600x2.h delete mode 100644 sphincsplus/shake-a64/f1600x2.s delete mode 100644 sphincsplus/shake-a64/f1600x2_const.c delete mode 120000 sphincsplus/shake-a64/fips202.c delete mode 120000 sphincsplus/shake-a64/fips202.h delete mode 100644 sphincsplus/shake-a64/fips202x2.c delete mode 100644 sphincsplus/shake-a64/fips202x2.h delete mode 100644 sphincsplus/shake-a64/fors.c delete mode 120000 sphincsplus/shake-a64/fors.h delete mode 120000 sphincsplus/shake-a64/hash.h delete mode 120000 sphincsplus/shake-a64/hash_shake.c delete mode 100644 sphincsplus/shake-a64/hash_shakex2.c delete mode 100644 sphincsplus/shake-a64/hashx2.h delete mode 100644 sphincsplus/shake-a64/merkle.c delete mode 120000 sphincsplus/shake-a64/merkle.h delete mode 120000 sphincsplus/shake-a64/params.h delete mode 120000 sphincsplus/shake-a64/params/params-sphincs-shake-128f.h delete mode 120000 sphincsplus/shake-a64/params/params-sphincs-shake-128s.h delete mode 120000 sphincsplus/shake-a64/params/params-sphincs-shake-192f.h delete mode 120000 sphincsplus/shake-a64/params/params-sphincs-shake-192s.h delete mode 120000 sphincsplus/shake-a64/params/params-sphincs-shake-256f.h delete mode 120000 sphincsplus/shake-a64/params/params-sphincs-shake-256s.h delete mode 120000 sphincsplus/shake-a64/randombytes.c delete mode 120000 sphincsplus/shake-a64/randombytes.h delete mode 120000 sphincsplus/shake-a64/rng.c delete mode 120000 sphincsplus/shake-a64/rng.h delete mode 120000 sphincsplus/shake-a64/shake_offsets.h delete mode 120000 sphincsplus/shake-a64/sign.c delete mode 100644 sphincsplus/shake-a64/test/benchmark.c delete mode 120000 sphincsplus/shake-a64/test/cycles.c delete mode 120000 sphincsplus/shake-a64/test/fors.c delete mode 120000 sphincsplus/shake-a64/test/spx.c delete mode 100644 sphincsplus/shake-a64/test/thashx2.c delete mode 100644 sphincsplus/shake-a64/thash.h delete mode 100644 sphincsplus/shake-a64/thash_shake_robustx2.c delete mode 100644 sphincsplus/shake-a64/thash_shake_simplex2.c delete mode 100644 sphincsplus/shake-a64/thashx2.h delete mode 120000 sphincsplus/shake-a64/utils.c delete mode 120000 sphincsplus/shake-a64/utils.h delete mode 100644 sphincsplus/shake-a64/utilsx2.c delete mode 100644 sphincsplus/shake-a64/utilsx2.h delete mode 100644 sphincsplus/shake-a64/wots.c delete mode 120000 sphincsplus/shake-a64/wots.h delete mode 100644 sphincsplus/shake-a64/wotsx2.h delete mode 100644 sphincsplus/shake-avx2/.gitignore delete mode 100644 sphincsplus/shake-avx2/Makefile delete mode 120000 sphincsplus/shake-avx2/PQCgenKAT_sign.c delete mode 120000 sphincsplus/shake-avx2/address.c delete mode 120000 sphincsplus/shake-avx2/address.h delete mode 120000 sphincsplus/shake-avx2/api.h delete mode 100644 sphincsplus/shake-avx2/context.h delete mode 120000 sphincsplus/shake-avx2/fips202.c delete mode 120000 sphincsplus/shake-avx2/fips202.h delete mode 100644 sphincsplus/shake-avx2/fips202x4.c delete mode 100644 sphincsplus/shake-avx2/fips202x4.h delete mode 100644 sphincsplus/shake-avx2/fors.c delete mode 120000 sphincsplus/shake-avx2/fors.h delete mode 120000 sphincsplus/shake-avx2/hash.h delete mode 120000 sphincsplus/shake-avx2/hash_shake.c delete mode 100644 sphincsplus/shake-avx2/hash_shakex4.c delete mode 100644 sphincsplus/shake-avx2/hashx4.h delete mode 100644 sphincsplus/shake-avx2/keccak4x/KeccakP-1600-times4-SIMD256.c delete mode 100644 sphincsplus/shake-avx2/keccak4x/KeccakP-1600-times4-SnP.h delete mode 100644 sphincsplus/shake-avx2/keccak4x/KeccakP-1600-unrolling.macros delete mode 100644 sphincsplus/shake-avx2/keccak4x/SIMD256-config.h delete mode 100644 sphincsplus/shake-avx2/keccak4x/align.h delete mode 100644 sphincsplus/shake-avx2/keccak4x/brg_endian.h delete mode 100644 sphincsplus/shake-avx2/merkle.c delete mode 120000 sphincsplus/shake-avx2/merkle.h delete mode 120000 sphincsplus/shake-avx2/params.h delete mode 120000 sphincsplus/shake-avx2/params/params-sphincs-shake-128f.h delete mode 120000 sphincsplus/shake-avx2/params/params-sphincs-shake-128s.h delete mode 120000 sphincsplus/shake-avx2/params/params-sphincs-shake-192f.h delete mode 120000 sphincsplus/shake-avx2/params/params-sphincs-shake-192s.h delete mode 120000 sphincsplus/shake-avx2/params/params-sphincs-shake-256f.h delete mode 120000 sphincsplus/shake-avx2/params/params-sphincs-shake-256s.h delete mode 120000 sphincsplus/shake-avx2/randombytes.c delete mode 120000 sphincsplus/shake-avx2/randombytes.h delete mode 120000 sphincsplus/shake-avx2/rng.c delete mode 120000 sphincsplus/shake-avx2/rng.h delete mode 120000 sphincsplus/shake-avx2/shake_offsets.h delete mode 120000 sphincsplus/shake-avx2/sign.c delete mode 100644 sphincsplus/shake-avx2/test/benchmark.c delete mode 120000 sphincsplus/shake-avx2/test/fors.c delete mode 120000 sphincsplus/shake-avx2/test/spx.c delete mode 100644 sphincsplus/shake-avx2/test/thashx4.c delete mode 120000 sphincsplus/shake-avx2/thash.h delete mode 120000 sphincsplus/shake-avx2/thash_shake_robust.c delete mode 100644 sphincsplus/shake-avx2/thash_shake_robustx4.c delete mode 120000 sphincsplus/shake-avx2/thash_shake_simple.c delete mode 100644 sphincsplus/shake-avx2/thash_shake_simplex4.c delete mode 100644 sphincsplus/shake-avx2/thashx4.h delete mode 120000 sphincsplus/shake-avx2/utils.c delete mode 120000 sphincsplus/shake-avx2/utils.h delete mode 100644 sphincsplus/shake-avx2/utilsx4.c delete mode 100644 sphincsplus/shake-avx2/utilsx4.h delete mode 100644 sphincsplus/shake-avx2/wots.c delete mode 120000 sphincsplus/shake-avx2/wots.h delete mode 100644 sphincsplus/shake-avx2/wotsx4.h delete mode 100755 sphincsplus/vectors.py diff --git a/dilithium/.gitignore b/dilithium/.gitignore deleted file mode 100644 index 17ace0a..0000000 --- a/dilithium/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -PQCsignKAT_Dilithium2.req -PQCsignKAT_Dilithium2.rsp -PQCsignKAT_Dilithium3.req -PQCsignKAT_Dilithium3.rsp -PQCsignKAT_Dilithium5.req -PQCsignKAT_Dilithium5.rsp -tvecs2 -tvecs3 -tvecs5 diff --git a/dilithium/.travis.yml b/dilithium/.travis.yml deleted file mode 100644 index d389f46..0000000 --- a/dilithium/.travis.yml +++ /dev/null @@ -1,33 +0,0 @@ -language: c -os: linux -dist: bionic -compiler: - - gcc - - clang -arch: - - amd64 - - arm64 - - ppc64le - - s390x -script: ./runtests.sh - -jobs: - include: - - os: osx - osx_image: xcode11.6 - compiler: clang - env: - - CFLAGS="-I/usr/local/opt/openssl@1.1/include/" - - NISTFLAGS="-I/usr/local/opt/openssl@1.1/include/" - - LDFLAGS="-L/usr/local/opt/openssl@1.1/lib/" - - - stage: coverage - os: linux - compiler: gcc - before_install: - - sudo apt-get update - - sudo apt-get install -y lcov - - gem install coveralls-lcov - script: ./runlcov.sh - after_success: - - coveralls-lcov ref/dilithium.lcov diff --git a/dilithium/AUTHORS.md b/dilithium/AUTHORS.md deleted file mode 100644 index 251f92c..0000000 --- a/dilithium/AUTHORS.md +++ /dev/null @@ -1,7 +0,0 @@ -Léo Ducas, -Eike Kiltz, -Tancrède Lepoint, -Vadim Lyubashevsky, -Gregor Seiler, -Peter Schwabe, -Damien Stehlé diff --git a/dilithium/Common_META.yml b/dilithium/Common_META.yml deleted file mode 100644 index 2efae86..0000000 --- a/dilithium/Common_META.yml +++ /dev/null @@ -1,15 +0,0 @@ -commons: - - name: common_ref - folder_name: ref - sources: fips202.c fips202.h - - name: common_avx2 - folder_name: avx2 - sources: f1600x4.S fips202.c fips202.h fips202x4.c fips202x4.h - supported_platforms: - - architecture: x86_64 - operating_systems: - - Darwin - - Linux - required_flags: - - avx2 - - popcnt diff --git a/dilithium/Dilithium2_META.yml b/dilithium/Dilithium2_META.yml deleted file mode 100644 index 122b3ca..0000000 --- a/dilithium/Dilithium2_META.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Dilithium2 -type: signature -claimed-nist-level: 2 -length-public-key: 1312 -length-secret-key: 2560 -length-signature: 2420 -nistkat-sha256: 9a196e7fb32fbc93757dc2d8dc1924460eab66303c0c08aeb8b798fb8d8f8cf3 -testvectors-sha256: 5f0d135c0f7fd43f3fb9727265fcd6ec3651eb8c67c04ea5f3d8dfa1d99740d2 -principal-submitters: - - Vadim Lyubashevsky -auxiliary-submitters: - - Shi Bai - - Léo Ducas - - Eike Kiltz - - Tancrède Lepoint - - Peter Schwabe - - Gregor Seiler - - Damien Stehlé -implementations: - - name: ref - version: https://github.com/pq-crystals/dilithium/tree/master - folder_name: ref - compile_opts: -DDILITHIUM_MODE=2 -DDILITHIUM_RANDOMIZED_SIGNING - signature_keypair: pqcrystals_dilithium2_ref_keypair - signature_signature: pqcrystals_dilithium2_ref_signature - signature_verify: pqcrystals_dilithium2_ref_verify - sources: ../LICENSE api.h config.h params.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.c ntt.h reduce.c reduce.h rounding.c rounding.h symmetric.h fips202.h symmetric-shake.c - common_dep: common_ref - - name: avx2 - version: https://github.com/pq-crystals/dilithium/tree/master - compile_opts: -DDILITHIUM_MODE=2 -DDILITHIUM_RANDOMIZED_SIGNING - signature_keypair: pqcrystals_dilithium2_avx2_keypair - signature_signature: pqcrystals_dilithium2_avx2_signature - signature_verify: pqcrystals_dilithium2_avx2_verify - sources: ../LICENSE api.h config.h params.h align.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.S invntt.S pointwise.S ntt.h shuffle.S shuffle.inc consts.c consts.h rejsample.c rejsample.h rounding.c rounding.h symmetric.h fips202.h fips202x4.h symmetric-shake.c - common_dep: common_avx2 - supported_platforms: - - architecture: x86_64 - operating_systems: - - Darwin - - Linux - required_flags: - - avx2 - - popcnt diff --git a/dilithium/Dilithium3_META.yml b/dilithium/Dilithium3_META.yml deleted file mode 100644 index b108b4f..0000000 --- a/dilithium/Dilithium3_META.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Dilithium3 -type: signature -claimed-nist-level: 3 -length-public-key: 1952 -length-secret-key: 4032 -length-signature: 3309 -nistkat-sha256: 7cb96242eac9907a55b5c84c202f0ebd552419c50b2e986dc2e28f07ecebf072 -testvectors-sha256: 14bf84918ee90e7afbd580191d3eb890d4557e0900b1145e39a8399ef7dd3fba -principal-submitters: - - Vadim Lyubashevsky -auxiliary-submitters: - - Shi Bai - - Léo Ducas - - Eike Kiltz - - Tancrède Lepoint - - Peter Schwabe - - Gregor Seiler - - Damien Stehlé -implementations: - - name: ref - version: https://github.com/pq-crystals/dilithium/tree/master - folder_name: ref - compile_opts: -DDILITHIUM_MODE=3 -DDILITHIUM_RANDOMIZED_SIGNING - signature_keypair: pqcrystals_dilithium3_ref_keypair - signature_signature: pqcrystals_dilithium3_ref_signature - signature_verify: pqcrystals_dilithium3_ref_verify - sources: ../LICENSE api.h config.h params.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.c ntt.h reduce.c reduce.h rounding.c rounding.h symmetric.h fips202.h symmetric-shake.c - common_dep: common_ref - - name: avx2 - version: https://github.com/pq-crystals/dilithium/tree/master - compile_opts: -DDILITHIUM_MODE=3 -DDILITHIUM_RANDOMIZED_SIGNING - signature_keypair: pqcrystals_dilithium3_avx2_keypair - signature_signature: pqcrystals_dilithium3_avx2_signature - signature_verify: pqcrystals_dilithium3_avx2_verify - sources: ../LICENSE api.h config.h params.h align.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.S invntt.S pointwise.S ntt.h shuffle.S shuffle.inc consts.c consts.h rejsample.c rejsample.h rounding.c rounding.h symmetric.h fips202.h fips202x4.h symmetric-shake.c - common_dep: common_avx2 - supported_platforms: - - architecture: x86_64 - operating_systems: - - Darwin - - Linux - required_flags: - - avx2 - - popcnt diff --git a/dilithium/Dilithium5_META.yml b/dilithium/Dilithium5_META.yml deleted file mode 100644 index 5163526..0000000 --- a/dilithium/Dilithium5_META.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Dilithium5 -type: signature -claimed-nist-level: 5 -length-public-key: 2592 -length-secret-key: 4896 -length-signature: 4627 -nistkat-sha256: 4537905d2aabcf302fab2f242baed293459ecda7c230e6a67063b02c7e2840ed -testvectors-sha256: 759a3ba35210c7e27ff90a7ce5e399295533b82ef125e6ec98af158e00268e44 -principal-submitters: - - Vadim Lyubashevsky -auxiliary-submitters: - - Shi Bai - - Léo Ducas - - Eike Kiltz - - Tancrède Lepoint - - Peter Schwabe - - Gregor Seiler - - Damien Stehlé -implementations: - - name: ref - version: https://github.com/pq-crystals/dilithium/tree/master - folder_name: ref - compile_opts: -DDILITHIUM_MODE=5 -DDILITHIUM_RANDOMIZED_SIGNING - signature_keypair: pqcrystals_dilithium5_ref_keypair - signature_signature: pqcrystals_dilithium5_ref_signature - signature_verify: pqcrystals_dilithium5_ref_verify - sources: ../LICENSE api.h config.h params.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.c ntt.h reduce.c reduce.h rounding.c rounding.h symmetric.h fips202.h symmetric-shake.c - common_dep: common_ref - - name: avx2 - version: https://github.com/pq-crystals/dilithium/tree/master - compile_opts: -DDILITHIUM_MODE=5 -DDILITHIUM_RANDOMIZED_SIGNING - signature_keypair: pqcrystals_dilithium5_avx2_keypair - signature_signature: pqcrystals_dilithium5_avx2_signature - signature_verify: pqcrystals_dilithium5_avx2_verify - sources: ../LICENSE api.h config.h params.h align.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.S invntt.S pointwise.S ntt.h shuffle.S shuffle.inc consts.c consts.h rejsample.c rejsample.h rounding.c rounding.h symmetric.h fips202.h fips202x4.h symmetric-shake.c - common_dep: common_avx2 - supported_platforms: - - architecture: x86_64 - operating_systems: - - Darwin - - Linux - required_flags: - - avx2 - - popcnt diff --git a/dilithium/LICENSE b/dilithium/LICENSE deleted file mode 100644 index cddfe61..0000000 --- a/dilithium/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -Public Domain (https://creativecommons.org/share-your-work/public-domain/cc0/); -or Apache 2.0 License (https://www.apache.org/licenses/LICENSE-2.0.html). - -For Keccak and the random number generator -we are using public-domain code from sources -and by authors listed in comments on top of -the respective files. diff --git a/dilithium/README.md b/dilithium/README.md deleted file mode 100644 index 9204fa6..0000000 --- a/dilithium/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# Dilithium - -[![Build Status](https://travis-ci.org/pq-crystals/dilithium.svg?branch=master)](https://travis-ci.org/pq-crystals/dilithium) [![Coverage Status](https://coveralls.io/repos/github/pq-crystals/dilithium/badge.svg?branch=master)](https://coveralls.io/github/pq-crystals/dilithium?branch=master) - -This repository contains the official reference implementation of the [Dilithium](https://www.pq-crystals.org/dilithium/) signature scheme, and an optimized implementation for x86 CPUs supporting the AVX2 instruction set. Dilithium is standardized as [FIPS 204](https://csrc.nist.gov/pubs/fips/204/final). - -## Build instructions - -The implementations contain several test and benchmarking programs and a Makefile to facilitate compilation. - -### Prerequisites - -Some of the test programs require [OpenSSL](https://openssl.org). If the OpenSSL header files and/or shared libraries do not lie in one of the standard locations on your system, it is necessary to specify their location via compiler and linker flags in the environment variables `CFLAGS`, `NISTFLAGS`, and `LDFLAGS`. - -For example, on macOS you can install OpenSSL via [Homebrew](https://brew.sh) by running -```sh -brew install openssl -``` -Then, run -```sh -export CFLAGS="-I/opt/homebrew/opt/openssl@1.1/include" -export NISTFLAGS="-I/opt/homebrew/opt/openssl@1.1/include" -export LDFLAGS="-L/opt/homebrew/opt/openssl@1.1/lib" -``` -before compilation to add the OpenSSL header and library locations to the respective search paths. - -### Test programs - -To compile the test programs on Linux or macOS, go to the `ref/` or `avx2/` directory and run -```sh -make -``` -This produces the executables -```sh -test/test_dilithium$ALG -test/test_vectors$ALG -``` -where `$ALG` ranges over the parameter sets 2, 3, and 5. - -* `test_dilithium$ALG` tests 10000 times to generate keys, sign a random message of 59 bytes and verify the produced signature. Also, the program will try to verify wrong signatures where a single random byte of a valid signature was randomly distorted. The program will abort with an error message and return -1 if there was an error. Otherwise it will output the key and signature sizes and return 0. -* `test_vectors$ALG` performs further tests of internal functions and prints deterministically generated test vectors for several intermediate values that occur in the Dilithium algorithms. Namely, a 48 byte seed, the matrix A corresponding to the first 32 bytes of seed, a short secret vector s corresponding to the first 32 bytes of seed and nonce 0, a masking vector y corresponding to the seed and nonce 0, the high bits w1 and the low bits w0 of the vector w = Ay, the power-of-two rounding t1 of w and the corresponding low part t0, and the challenge c for the seed and w1. This program is meant to help to ensure compatibility of independent implementations. - -### Benchmarking programs - -For benchmarking the implementations, we provide speed test programs for x86 CPUs that use the Time Step Counter (TSC) or the actual cycle counter provided by the Performance Measurement Counters (PMC) to measure performance. To compile the programs run -```sh -make speed -``` -This produces the executables -```sh -test/test_speed$ALG -``` -for all parameter sets `$ALG` as above. The programs report the median and average cycle counts of 10000 executions of various internal functions and the API functions for key generation, signing and verification. By default the Time Step Counter is used. If instead you want to obtain the actual cycle counts from the Performance Measurement Counters export `CFLAGS="-DUSE_RDPMC"` before compilation. - -Please note that the reference implementation in `ref/` is not optimized for any platform, and, since it prioritises clean code, is significantly slower than a trivially optimized but still platform-independent implementation. Hence benchmarking the reference code does not provide representative results. - -Our Dilithium implementations are contained in the [SUPERCOP](https://bench.cr.yp.to) benchmarking framework. See [here](http://bench.cr.yp.to/results-sign.html#amd64-kizomba) for current cycle counts on an Intel KabyLake CPU. - -## Randomized signing - -By default our code implements Dilithium's hedged signing mode. To change this to the deterministic signing mode, undefine the `DILITHIUM_RANDOMIZED_SIGNING` preprocessor macro at compilation by either commenting the line -```sh -#define DILITHIUM_RANDOMIZED_SIGNING -``` -in config.h, or adding `-UDILITHIUM_RANDOMIZED_SIGNING` to the compiler flags in the environment variable `CFLAGS`. - -## Shared libraries - -All implementations can be compiled into shared libraries by running -```sh -make shared -``` -For example in the directory `ref/` of the reference implementation, this produces the libraries -```sh -libpqcrystals_dilithium$ALG_ref.so -``` -for all parameter sets `$ALG`, and the required symmetric crypto library -``` -libpqcrystals_fips202_ref.so -``` -All global symbols in the libraries lie in the namespaces `pqcrystals_dilithium$ALG_ref` and `libpqcrystals_fips202_ref`. Hence it is possible to link a program against all libraries simultaneously and obtain access to all implementations for all parameter sets. The corresponding API header file is `ref/api.h`, which contains prototypes for all API functions and preprocessor defines for the key and signature lengths. diff --git a/dilithium/SHA256SUMS b/dilithium/SHA256SUMS deleted file mode 100644 index 3e5914f..0000000 --- a/dilithium/SHA256SUMS +++ /dev/null @@ -1,3 +0,0 @@ -5f0d135c0f7fd43f3fb9727265fcd6ec3651eb8c67c04ea5f3d8dfa1d99740d2 tvecs2 -14bf84918ee90e7afbd580191d3eb890d4557e0900b1145e39a8399ef7dd3fba tvecs3 -759a3ba35210c7e27ff90a7ce5e399295533b82ef125e6ec98af158e00268e44 tvecs5 diff --git a/dilithium/avx2/.gitignore b/dilithium/avx2/.gitignore deleted file mode 100644 index cc78368..0000000 --- a/dilithium/avx2/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.so -*.o diff --git a/dilithium/avx2/Makefile b/dilithium/avx2/Makefile deleted file mode 100644 index f85cfc0..0000000 --- a/dilithium/avx2/Makefile +++ /dev/null @@ -1,118 +0,0 @@ -CC ?= /usr/bin/cc -CFLAGS += -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wredundant-decls \ - -Wshadow -Wpointer-arith -mavx2 -mpopcnt \ - -march=native -mtune=native -O3 -NISTFLAGS += -Wno-unused-result -mavx2 -mpopcnt \ - -march=native -mtune=native -O3 -SOURCES = sign.c packing.c polyvec.c poly.c ntt.S invntt.S pointwise.S \ - shuffle.S consts.c rejsample.c rounding.c -HEADERS = align.h config.h params.h api.h sign.h packing.h polyvec.h poly.h ntt.h \ - consts.h shuffle.inc rejsample.h rounding.h symmetric.h randombytes.h -KECCAK_SOURCES = $(SOURCES) fips202.c fips202x4.c f1600x4.S symmetric-shake.c -KECCAK_HEADERS = $(HEADERS) fips202.h fips202x4.h - -.PHONY: all shared clean - -all: \ - test/test_dilithium2 \ - test/test_dilithium3 \ - test/test_dilithium5 \ - test/test_vectors2 \ - test/test_vectors3 \ - test/test_vectors5 \ - speed - -speed: \ - test/test_speed2 \ - test/test_speed3 \ - test/test_speed5 \ - -shared: \ - libpqcrystals_dilithium2_avx2.so \ - libpqcrystals_dilithium3_avx2.so \ - libpqcrystals_dilithium5_avx2.so \ - libpqcrystals_fips202_avx2.so \ - libpqcrystals_fips202x4_avx2.so \ - -libpqcrystals_fips202_avx2.so: fips202.c fips202.h - $(CC) -shared -fPIC $(CFLAGS) -o $@ $< - -libpqcrystals_fips202x4_avx2.so: fips202x4.c fips202x4.h f1600x4.S - $(CC) -shared -fPIC $(CFLAGS) -o $@ $< f1600x4.S - -libpqcrystals_dilithium2_avx2.so: $(SOURCES) $(HEADERS) symmetric-shake.c - $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=2 \ - -o $@ $(SOURCES) symmetric-shake.c - -libpqcrystals_dilithium3_avx2.so: $(SOURCES) $(HEADERS) symmetric-shake.c - $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=3 \ - -o $@ $(SOURCES) symmetric-shake.c - -libpqcrystals_dilithium5_avx2.so: $(SOURCES) $(HEADERS) symmetric-shake.c - $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=5 \ - -o $@ $(SOURCES) symmetric-shake.c - -test/test_dilithium2: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ - -o $@ $< randombytes.c $(KECCAK_SOURCES) - -test/test_dilithium3: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ - -o $@ $< randombytes.c $(KECCAK_SOURCES) - -test/test_dilithium5: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ - -o $@ $< randombytes.c $(KECCAK_SOURCES) - -test/test_vectors2: test/test_vectors.c $(KECCAK_SOURCES) $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ - -o $@ $< $(KECCAK_SOURCES) - -test/test_vectors3: test/test_vectors.c $(KECCAK_SOURCES) $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ - -o $@ $< $(KECCAK_SOURCES) - -test/test_vectors5: test/test_vectors.c $(KECCAK_SOURCES) $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ - -o $@ $< $(KECCAK_SOURCES) - -test/test_speed2: test/test_speed.c test/speed_print.c test/speed_print.h \ - test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ - -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ - $(KECCAK_SOURCES) - -test/test_speed3: test/test_speed.c test/speed_print.c test/speed_print.h \ - test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ - -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ - $(KECCAK_SOURCES) - -test/test_speed5: test/test_speed.c test/speed_print.c test/speed_print.h \ - test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ - -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ - $(KECCAK_SOURCES) - -test/test_mul: test/test_mul.c randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -UDBENCH -o $@ $< randombytes.c $(KECCAK_SOURCES) - -clean: - rm -f *.o *.a *.so - rm -f test/test_dilithium2 - rm -f test/test_dilithium3 - rm -f test/test_dilithium5 - rm -f test/test_vectors2 - rm -f test/test_vectors3 - rm -f test/test_vectors5 - rm -f test/test_speed2 - rm -f test/test_speed3 - rm -f test/test_speed5 - rm -f test/test_mul diff --git a/dilithium/avx2/align.h b/dilithium/avx2/align.h deleted file mode 100644 index 33fac1d..0000000 --- a/dilithium/avx2/align.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ALIGN_H -#define ALIGN_H - -#include -#include - -#define ALIGNED_UINT8(N) \ - union { \ - uint8_t coeffs[N]; \ - __m256i vec[(N+31)/32]; \ - } - -#define ALIGNED_INT32(N) \ - union { \ - int32_t coeffs[N]; \ - __m256i vec[(N+7)/8]; \ - } - -#endif diff --git a/dilithium/avx2/api.h b/dilithium/avx2/api.h deleted file mode 100644 index 36ec622..0000000 --- a/dilithium/avx2/api.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef API_H -#define API_H - -#include -#include - -#define pqcrystals_dilithium2_PUBLICKEYBYTES 1312 -#define pqcrystals_dilithium2_SECRETKEYBYTES 2560 -#define pqcrystals_dilithium2_BYTES 2420 - -#define pqcrystals_dilithium2_avx2_PUBLICKEYBYTES pqcrystals_dilithium2_PUBLICKEYBYTES -#define pqcrystals_dilithium2_avx2_SECRETKEYBYTES pqcrystals_dilithium2_SECRETKEYBYTES -#define pqcrystals_dilithium2_avx2_BYTES pqcrystals_dilithium2_BYTES - -int pqcrystals_dilithium2_avx2_keypair(uint8_t *pk, uint8_t *sk); - -int pqcrystals_dilithium2_avx2_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium2_avx2(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium2_avx2_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - -int pqcrystals_dilithium2_avx2_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - - -#define pqcrystals_dilithium3_PUBLICKEYBYTES 1952 -#define pqcrystals_dilithium3_SECRETKEYBYTES 4032 -#define pqcrystals_dilithium3_BYTES 3309 - -#define pqcrystals_dilithium3_avx2_PUBLICKEYBYTES pqcrystals_dilithium3_PUBLICKEYBYTES -#define pqcrystals_dilithium3_avx2_SECRETKEYBYTES pqcrystals_dilithium3_SECRETKEYBYTES -#define pqcrystals_dilithium3_avx2_BYTES pqcrystals_dilithium3_BYTES - -int pqcrystals_dilithium3_avx2_keypair(uint8_t *pk, uint8_t *sk); - -int pqcrystals_dilithium3_avx2_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium3_avx2(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium3_avx2_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - -int pqcrystals_dilithium3_avx2_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - - -#define pqcrystals_dilithium5_PUBLICKEYBYTES 2592 -#define pqcrystals_dilithium5_SECRETKEYBYTES 4896 -#define pqcrystals_dilithium5_BYTES 4627 - -#define pqcrystals_dilithium5_avx2_PUBLICKEYBYTES pqcrystals_dilithium5_PUBLICKEYBYTES -#define pqcrystals_dilithium5_avx2_SECRETKEYBYTES pqcrystals_dilithium5_SECRETKEYBYTES -#define pqcrystals_dilithium5_avx2_BYTES pqcrystals_dilithium5_BYTES - -int pqcrystals_dilithium5_avx2_keypair(uint8_t *pk, uint8_t *sk); - -int pqcrystals_dilithium5_avx2_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium5_avx2(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium5_avx2_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - -int pqcrystals_dilithium5_avx2_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - - -#endif diff --git a/dilithium/avx2/config.h b/dilithium/avx2/config.h deleted file mode 100644 index a9facc0..0000000 --- a/dilithium/avx2/config.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -//#define DILITHIUM_MODE 2 -#define DILITHIUM_RANDOMIZED_SIGNING -//#define USE_RDPMC -//#define DBENCH - -#ifndef DILITHIUM_MODE -#define DILITHIUM_MODE 2 -#endif - -#if DILITHIUM_MODE == 2 -#define CRYPTO_ALGNAME "Dilithium2" -#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium2_avx2 -#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium2_avx2_##s -#elif DILITHIUM_MODE == 3 -#define CRYPTO_ALGNAME "Dilithium3" -#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium3_avx2 -#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium3_avx2_##s -#elif DILITHIUM_MODE == 5 -#define CRYPTO_ALGNAME "Dilithium5" -#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium5_avx2 -#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium5_avx2_##s -#endif - -#endif diff --git a/dilithium/avx2/consts.c b/dilithium/avx2/consts.c deleted file mode 100644 index 414d99e..0000000 --- a/dilithium/avx2/consts.c +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include "params.h" -#include "consts.h" - -#define QINV 58728449 // q^(-1) mod 2^32 -#define MONT -4186625 // 2^32 mod q -#define DIV 41978 // mont^2/256 -#define DIV_QINV -8395782 - -const qdata_t qdata = {{ -#define _8XQ 0 - Q, Q, Q, Q, Q, Q, Q, Q, - -#define _8XQINV 8 - QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, - -#define _8XDIV_QINV 16 - DIV_QINV, DIV_QINV, DIV_QINV, DIV_QINV, DIV_QINV, DIV_QINV, DIV_QINV, DIV_QINV, - -#define _8XDIV 24 - DIV, DIV, DIV, DIV, DIV, DIV, DIV, DIV, - -#define _ZETAS_QINV 32 - -151046689, 1830765815, -1929875198, -1927777021, 1640767044, 1477910808, 1612161320, 1640734244, - 308362795, 308362795, 308362795, 308362795, -1815525077, -1815525077, -1815525077, -1815525077, - -1374673747, -1374673747, -1374673747, -1374673747, -1091570561, -1091570561, -1091570561, -1091570561, - -1929495947, -1929495947, -1929495947, -1929495947, 515185417, 515185417, 515185417, 515185417, - -285697463, -285697463, -285697463, -285697463, 625853735, 625853735, 625853735, 625853735, - 1727305304, 1727305304, 2082316400, 2082316400, -1364982364, -1364982364, 858240904, 858240904, - 1806278032, 1806278032, 222489248, 222489248, -346752664, -346752664, 684667771, 684667771, - 1654287830, 1654287830, -878576921, -878576921, -1257667337, -1257667337, -748618600, -748618600, - 329347125, 329347125, 1837364258, 1837364258, -1443016191, -1443016191, -1170414139, -1170414139, - -1846138265, -1631226336, -1404529459, 1838055109, 1594295555, -1076973524, -1898723372, -594436433, - -202001019, -475984260, -561427818, 1797021249, -1061813248, 2059733581, -1661512036, -1104976547, - -1750224323, -901666090, 418987550, 1831915353, -1925356481, 992097815, 879957084, 2024403852, - 1484874664, -1636082790, -285388938, -1983539117, -1495136972, -950076368, -1714807468, -952438995, - -1574918427, 1350681039, -2143979939, 1599739335, -1285853323, -993005454, -1440787840, 568627424, - -783134478, -588790216, 289871779, -1262003603, 2135294594, -1018755525, -889861155, 1665705315, - 1321868265, 1225434135, -1784632064, 666258756, 675310538, -1555941048, -1999506068, -1499481951, - -695180180, -1375177022, 1777179795, 334803717, -178766299, -518252220, 1957047970, 1146323031, - -654783359, -1974159335, 1651689966, 140455867, -1039411342, 1955560694, 1529189038, -2131021878, - -247357819, 1518161567, -86965173, 1708872713, 1787797779, 1638590967, -120646188, -1669960606, - -916321552, 1155548552, 2143745726, 1210558298, -1261461890, -318346816, 628664287, -1729304568, - 1422575624, 1424130038, -1185330464, 235321234, 168022240, 1206536194, 985155484, -894060583, - -898413, -1363460238, -605900043, 2027833504, 14253662, 1014493059, 863641633, 1819892093, - 2124962073, -1223601433, -1920467227, -1637785316, -1536588520, 694382729, 235104446, -1045062172, - 831969619, -300448763, 756955444, -260312805, 1554794072, 1339088280, -2040058690, -853476187, - -2047270596, -1723816713, -1591599803, -440824168, 1119856484, 1544891539, 155290192, -973777462, - 991903578, 912367099, -44694137, 1176904444, -421552614, -818371958, 1747917558, -325927722, - 908452108, 1851023419, -1176751719, -1354528380, -72690498, -314284737, 985022747, 963438279, - -1078959975, 604552167, -1021949428, 608791570, 173440395, -2126092136, -1316619236, -1039370342, - 6087993, -110126092, 565464272, -1758099917, -1600929361, 879867909, -1809756372, 400711272, - 1363007700, 30313375, -326425360, 1683520342, -517299994, 2027935492, -1372618620, 128353682, - -1123881663, 137583815, -635454918, -642772911, 45766801, 671509323, -2070602178, 419615363, - 1216882040, -270590488, -1276805128, 371462360, -1357098057, -384158533, 827959816, -596344473, - 702390549, -279505433, -260424530, -71875110, -1208667171, -1499603926, 2036925262, -540420426, - 746144248, -1420958686, 2032221021, 1904936414, 1257750362, 1926727420, 1931587462, 1258381762, - 885133339, 1629985060, 1967222129, 6363718, -1287922800, 1136965286, 1779436847, 1116720494, - 1042326957, 1405999311, 713994583, 940195359, -1542497137, 2061661095, -883155599, 1726753853, - -1547952704, 394851342, 283780712, 776003547, 1123958025, 201262505, 1934038751, 374860238, - -#define _ZETAS 328 - -3975713, 25847, -2608894, -518909, 237124, -777960, -876248, 466468, - 1826347, 1826347, 1826347, 1826347, 2353451, 2353451, 2353451, 2353451, - -359251, -359251, -359251, -359251, -2091905, -2091905, -2091905, -2091905, - 3119733, 3119733, 3119733, 3119733, -2884855, -2884855, -2884855, -2884855, - 3111497, 3111497, 3111497, 3111497, 2680103, 2680103, 2680103, 2680103, - 2725464, 2725464, 1024112, 1024112, -1079900, -1079900, 3585928, 3585928, - -549488, -549488, -1119584, -1119584, 2619752, 2619752, -2108549, -2108549, - -2118186, -2118186, -3859737, -3859737, -1399561, -1399561, -3277672, -3277672, - 1757237, 1757237, -19422, -19422, 4010497, 4010497, 280005, 280005, - 2706023, 95776, 3077325, 3530437, -1661693, -3592148, -2537516, 3915439, - -3861115, -3043716, 3574422, -2867647, 3539968, -300467, 2348700, -539299, - -1699267, -1643818, 3505694, -3821735, 3507263, -2140649, -1600420, 3699596, - 811944, 531354, 954230, 3881043, 3900724, -2556880, 2071892, -2797779, - -3930395, -3677745, -1452451, 2176455, -1257611, -4083598, -3190144, -3632928, - 3412210, 2147896, -2967645, -411027, -671102, -22981, -381987, 1852771, - -3343383, 508951, 44288, 904516, -3724342, 1653064, 2389356, 759969, - 189548, 3159746, -2409325, 1315589, 1285669, -812732, -3019102, -3628969, - -1528703, -3041255, 3475950, -1585221, 1939314, -1000202, -3157330, 126922, - -983419, 2715295, -3693493, -2477047, -1228525, -1308169, 1349076, -1430430, - 264944, 3097992, -1100098, 3958618, -8578, -3249728, -210977, -1316856, - -3553272, -1851402, -177440, 1341330, -1584928, -1439742, -3881060, 3839961, - 2091667, -3342478, 266997, -3520352, 900702, 495491, -655327, -3556995, - 342297, 3437287, 2842341, 4055324, -3767016, -2994039, -1333058, -451100, - -1279661, 1500165, -542412, -2584293, -2013608, 1957272, -3183426, 810149, - -3038916, 2213111, -426683, -1667432, -2939036, 183443, -554416, 3937738, - 3407706, 2244091, 2434439, -3759364, 1859098, -1613174, -3122442, -525098, - 286988, -3342277, 2691481, 1247620, 1250494, 1869119, 1237275, 1312455, - 1917081, 777191, -2831860, -3724270, 2432395, 3369112, 162844, 1652634, - 3523897, -975884, 1723600, -1104333, -2235985, -976891, 3919660, 1400424, - 2316500, -2446433, -1235728, -1197226, 909542, -43260, 2031748, -768622, - -2437823, 1735879, -2590150, 2486353, 2635921, 1903435, -3318210, 3306115, - -2546312, 2235880, -1671176, 594136, 2454455, 185531, 1616392, -3694233, - 3866901, 1717735, -1803090, -260646, -420899, 1612842, -48306, -846154, - 3817976, -3562462, 3513181, -3193378, 819034, -522500, 3207046, -3595838, - 4108315, 203044, 1265009, 1595974, -3548272, -1050970, -1430225, -1962642, - -1374803, 3406031, -1846953, -3776993, -164721, -1207385, 3014001, -1799107, - 269760, 472078, 1910376, -3833893, -2286327, -3545687, -1362209, 1976782, -}}; diff --git a/dilithium/avx2/consts.h b/dilithium/avx2/consts.h deleted file mode 100644 index 930d2f0..0000000 --- a/dilithium/avx2/consts.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef CONSTS_H -#define CONSTS_H - -#include "params.h" - -#define _8XQ 0 -#define _8XQINV 8 -#define _8XDIV_QINV 16 -#define _8XDIV 24 -#define _ZETAS_QINV 32 -#define _ZETAS 328 - -/* The C ABI on MacOS exports all symbols with a leading - * underscore. This means that any symbols we refer to from - * C files (functions) can't be found, and all symbols we - * refer to from ASM also can't be found. - * - * This define helps us get around this - */ -#if defined(__WIN32__) || defined(__APPLE__) -#define decorate(s) _##s -#define _cdecl(s) decorate(s) -#define cdecl(s) _cdecl(DILITHIUM_NAMESPACE(##s)) -#else -#define cdecl(s) DILITHIUM_NAMESPACE(##s) -#endif - -#ifndef __ASSEMBLER__ - -#include "align.h" - -typedef ALIGNED_INT32(624) qdata_t; - -#define qdata DILITHIUM_NAMESPACE(qdata) -extern const qdata_t qdata; - -#endif -#endif diff --git a/dilithium/avx2/f1600x4.S b/dilithium/avx2/f1600x4.S deleted file mode 100644 index 5455129..0000000 --- a/dilithium/avx2/f1600x4.S +++ /dev/null @@ -1,909 +0,0 @@ -/* Taken from Bas Westerbaan's new 4-way SHAKE implementation - * for Sphincs+ (https://github.com/sphincs/sphincsplus/pull/14/), - * but uses vpshufb for byte-granular rotations as in the Keccak Code Package. */ - -#include "fips202x4.h" - -.data -.p2align 5 -rho8: -.byte 7,0,1,2,3,4,5,6,15,8,9,10,11,12,13,14,7,0,1,2,3,4,5,6,15,8,9,10,11,12,13,14 -rho56: -.byte 1,2,3,4,5,6,7,0,9,10,11,12,13,14,15,8,1,2,3,4,5,6,7,0,9,10,11,12,13,14,15,8 - -.text -.global cdecl(f1600x4) -cdecl(f1600x4): -vmovdqa rho8(%rip), %ymm0 -movq $6, %rax -looptop: -vmovdqa 0(%rdi), %ymm8 -vmovdqa 32(%rdi), %ymm9 -vmovdqa 64(%rdi), %ymm10 -vmovdqa 96(%rdi), %ymm11 -vmovdqa 128(%rdi), %ymm12 -vpxor 160(%rdi), %ymm8, %ymm8 -vpxor 192(%rdi), %ymm9, %ymm9 -vpxor 224(%rdi), %ymm10, %ymm10 -vpxor 256(%rdi), %ymm11, %ymm11 -vpxor 288(%rdi), %ymm12, %ymm12 -vpxor 320(%rdi), %ymm8, %ymm8 -vpxor 352(%rdi), %ymm9, %ymm9 -vpxor 384(%rdi), %ymm10, %ymm10 -vpxor 416(%rdi), %ymm11, %ymm11 -vpxor 448(%rdi), %ymm12, %ymm12 -vpxor 480(%rdi), %ymm8, %ymm8 -vpxor 512(%rdi), %ymm9, %ymm9 -vpxor 544(%rdi), %ymm10, %ymm10 -vpxor 576(%rdi), %ymm11, %ymm11 -vpxor 608(%rdi), %ymm12, %ymm12 -vpxor 640(%rdi), %ymm8, %ymm8 -vpxor 672(%rdi), %ymm9, %ymm9 -vpxor 704(%rdi), %ymm10, %ymm10 -vpxor 736(%rdi), %ymm11, %ymm11 -vpxor 768(%rdi), %ymm12, %ymm12 -vpsllq $1, %ymm9, %ymm13 -vpsllq $1, %ymm10, %ymm14 -vpsllq $1, %ymm11, %ymm15 -vpsllq $1, %ymm12, %ymm7 -vpsllq $1, %ymm8, %ymm6 -vpsrlq $63, %ymm9, %ymm5 -vpsrlq $63, %ymm10, %ymm4 -vpsrlq $63, %ymm11, %ymm3 -vpsrlq $63, %ymm12, %ymm2 -vpsrlq $63, %ymm8, %ymm1 -vpor %ymm13, %ymm5, %ymm5 -vpor %ymm14, %ymm4, %ymm4 -vpor %ymm15, %ymm3, %ymm3 -vpor %ymm7, %ymm2, %ymm2 -vpor %ymm6, %ymm1, %ymm1 -vpxor %ymm5, %ymm12, %ymm5 -vpxor %ymm4, %ymm8, %ymm4 -vpxor %ymm3, %ymm9, %ymm3 -vpxor %ymm2, %ymm10, %ymm2 -vpxor %ymm1, %ymm11, %ymm1 -vpxor 0(%rdi), %ymm5, %ymm8 -vpxor 192(%rdi), %ymm4, %ymm9 -vpxor 384(%rdi), %ymm3, %ymm10 -vpxor 576(%rdi), %ymm2, %ymm11 -vpxor 768(%rdi), %ymm1, %ymm12 -vpsllq $44, %ymm9, %ymm14 -vpsllq $43, %ymm10, %ymm15 -vpsllq $21, %ymm11, %ymm7 -vpsllq $14, %ymm12, %ymm6 -vpsrlq $20, %ymm9, %ymm9 -vpsrlq $21, %ymm10, %ymm10 -vpsrlq $43, %ymm11, %ymm11 -vpsrlq $50, %ymm12, %ymm12 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vpbroadcastq 0(%rsi), %ymm8 -vpxor %ymm8, %ymm13, %ymm13 -vmovdqa %ymm13, 0(%rdi) -vmovdqa %ymm14, 192(%rdi) -vmovdqa %ymm15, 384(%rdi) -vmovdqa %ymm7, 576(%rdi) -vmovdqa %ymm6, 768(%rdi) -vpxor 96(%rdi), %ymm2, %ymm8 -vpxor 288(%rdi), %ymm1, %ymm9 -vpxor 320(%rdi), %ymm5, %ymm10 -vpxor 512(%rdi), %ymm4, %ymm11 -vpxor 704(%rdi), %ymm3, %ymm12 -vpsllq $28, %ymm8, %ymm13 -vpsllq $20, %ymm9, %ymm14 -vpsllq $3, %ymm10, %ymm15 -vpsllq $45, %ymm11, %ymm7 -vpsllq $61, %ymm12, %ymm6 -vpsrlq $36, %ymm8, %ymm8 -vpsrlq $44, %ymm9, %ymm9 -vpsrlq $61, %ymm10, %ymm10 -vpsrlq $19, %ymm11, %ymm11 -vpsrlq $3, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 320(%rdi) -vmovdqa %ymm14, 512(%rdi) -vmovdqa %ymm15, 704(%rdi) -vmovdqa %ymm7, 96(%rdi) -vmovdqa %ymm6, 288(%rdi) -vpxor 32(%rdi), %ymm4, %ymm8 -vpxor 224(%rdi), %ymm3, %ymm9 -vpxor 416(%rdi), %ymm2, %ymm10 -vpxor 608(%rdi), %ymm1, %ymm11 -vpxor 640(%rdi), %ymm5, %ymm12 -vpsllq $1, %ymm8, %ymm13 -vpsllq $6, %ymm9, %ymm14 -vpsllq $25, %ymm10, %ymm15 -#vpsllq $8, %ymm11, %ymm7 -vpsllq $18, %ymm12, %ymm6 -vpsrlq $63, %ymm8, %ymm8 -vpsrlq $58, %ymm9, %ymm9 -vpsrlq $39, %ymm10, %ymm10 -#vpsrlq $56, %ymm11, %ymm11 -vpsrlq $46, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -#vpor %ymm7, %ymm11, %ymm11 -vpshufb %ymm0, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 640(%rdi) -vmovdqa %ymm14, 32(%rdi) -vmovdqa %ymm15, 224(%rdi) -vmovdqa %ymm7, 416(%rdi) -vmovdqa %ymm6, 608(%rdi) -vpxor 128(%rdi), %ymm1, %ymm8 -vpxor 160(%rdi), %ymm5, %ymm9 -vpxor 352(%rdi), %ymm4, %ymm10 -vpxor 544(%rdi), %ymm3, %ymm11 -vpxor 736(%rdi), %ymm2, %ymm12 -vpsllq $27, %ymm8, %ymm13 -vpsllq $36, %ymm9, %ymm14 -vpsllq $10, %ymm10, %ymm15 -vpsllq $15, %ymm11, %ymm7 -#vpsllq $56, %ymm12, %ymm6 -vpsrlq $37, %ymm8, %ymm8 -vpsrlq $28, %ymm9, %ymm9 -vpsrlq $54, %ymm10, %ymm10 -vpsrlq $49, %ymm11, %ymm11 -#vpsrlq $8, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -#vpor %ymm6, %ymm12, %ymm12 -vpshufb rho56(%rip), %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 160(%rdi) -vmovdqa %ymm14, 352(%rdi) -vmovdqa %ymm15, 544(%rdi) -vmovdqa %ymm7, 736(%rdi) -vmovdqa %ymm6, 128(%rdi) -vpxor 64(%rdi), %ymm3, %ymm8 -vpxor 256(%rdi), %ymm2, %ymm9 -vpxor 448(%rdi), %ymm1, %ymm10 -vpxor 480(%rdi), %ymm5, %ymm11 -vpxor 672(%rdi), %ymm4, %ymm12 -vpsllq $62, %ymm8, %ymm13 -vpsllq $55, %ymm9, %ymm14 -vpsllq $39, %ymm10, %ymm15 -vpsllq $41, %ymm11, %ymm7 -vpsllq $2, %ymm12, %ymm6 -vpsrlq $2, %ymm8, %ymm8 -vpsrlq $9, %ymm9, %ymm9 -vpsrlq $25, %ymm10, %ymm10 -vpsrlq $23, %ymm11, %ymm11 -vpsrlq $62, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 480(%rdi) -vmovdqa %ymm14, 672(%rdi) -vmovdqa %ymm15, 64(%rdi) -vmovdqa %ymm7, 256(%rdi) -vmovdqa %ymm6, 448(%rdi) -vmovdqa 0(%rdi), %ymm8 -vmovdqa 32(%rdi), %ymm9 -vmovdqa 64(%rdi), %ymm10 -vmovdqa 96(%rdi), %ymm11 -vmovdqa 128(%rdi), %ymm12 -vpxor 160(%rdi), %ymm8, %ymm8 -vpxor 192(%rdi), %ymm9, %ymm9 -vpxor 224(%rdi), %ymm10, %ymm10 -vpxor 256(%rdi), %ymm11, %ymm11 -vpxor 288(%rdi), %ymm12, %ymm12 -vpxor 320(%rdi), %ymm8, %ymm8 -vpxor 352(%rdi), %ymm9, %ymm9 -vpxor 384(%rdi), %ymm10, %ymm10 -vpxor 416(%rdi), %ymm11, %ymm11 -vpxor 448(%rdi), %ymm12, %ymm12 -vpxor 480(%rdi), %ymm8, %ymm8 -vpxor 512(%rdi), %ymm9, %ymm9 -vpxor 544(%rdi), %ymm10, %ymm10 -vpxor 576(%rdi), %ymm11, %ymm11 -vpxor 608(%rdi), %ymm12, %ymm12 -vpxor 640(%rdi), %ymm8, %ymm8 -vpxor 672(%rdi), %ymm9, %ymm9 -vpxor 704(%rdi), %ymm10, %ymm10 -vpxor 736(%rdi), %ymm11, %ymm11 -vpxor 768(%rdi), %ymm12, %ymm12 -vpsllq $1, %ymm9, %ymm13 -vpsllq $1, %ymm10, %ymm14 -vpsllq $1, %ymm11, %ymm15 -vpsllq $1, %ymm12, %ymm7 -vpsllq $1, %ymm8, %ymm6 -vpsrlq $63, %ymm9, %ymm5 -vpsrlq $63, %ymm10, %ymm4 -vpsrlq $63, %ymm11, %ymm3 -vpsrlq $63, %ymm12, %ymm2 -vpsrlq $63, %ymm8, %ymm1 -vpor %ymm13, %ymm5, %ymm5 -vpor %ymm14, %ymm4, %ymm4 -vpor %ymm15, %ymm3, %ymm3 -vpor %ymm7, %ymm2, %ymm2 -vpor %ymm6, %ymm1, %ymm1 -vpxor %ymm5, %ymm12, %ymm5 -vpxor %ymm4, %ymm8, %ymm4 -vpxor %ymm3, %ymm9, %ymm3 -vpxor %ymm2, %ymm10, %ymm2 -vpxor %ymm1, %ymm11, %ymm1 -vpxor 0(%rdi), %ymm5, %ymm8 -vpxor 512(%rdi), %ymm4, %ymm9 -vpxor 224(%rdi), %ymm3, %ymm10 -vpxor 736(%rdi), %ymm2, %ymm11 -vpxor 448(%rdi), %ymm1, %ymm12 -vpsllq $44, %ymm9, %ymm14 -vpsllq $43, %ymm10, %ymm15 -vpsllq $21, %ymm11, %ymm7 -vpsllq $14, %ymm12, %ymm6 -vpsrlq $20, %ymm9, %ymm9 -vpsrlq $21, %ymm10, %ymm10 -vpsrlq $43, %ymm11, %ymm11 -vpsrlq $50, %ymm12, %ymm12 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vpbroadcastq 8(%rsi), %ymm8 -vpxor %ymm8, %ymm13, %ymm13 -vmovdqa %ymm13, 0(%rdi) -vmovdqa %ymm14, 512(%rdi) -vmovdqa %ymm15, 224(%rdi) -vmovdqa %ymm7, 736(%rdi) -vmovdqa %ymm6, 448(%rdi) -vpxor 576(%rdi), %ymm2, %ymm8 -vpxor 288(%rdi), %ymm1, %ymm9 -vpxor 640(%rdi), %ymm5, %ymm10 -vpxor 352(%rdi), %ymm4, %ymm11 -vpxor 64(%rdi), %ymm3, %ymm12 -vpsllq $28, %ymm8, %ymm13 -vpsllq $20, %ymm9, %ymm14 -vpsllq $3, %ymm10, %ymm15 -vpsllq $45, %ymm11, %ymm7 -vpsllq $61, %ymm12, %ymm6 -vpsrlq $36, %ymm8, %ymm8 -vpsrlq $44, %ymm9, %ymm9 -vpsrlq $61, %ymm10, %ymm10 -vpsrlq $19, %ymm11, %ymm11 -vpsrlq $3, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 640(%rdi) -vmovdqa %ymm14, 352(%rdi) -vmovdqa %ymm15, 64(%rdi) -vmovdqa %ymm7, 576(%rdi) -vmovdqa %ymm6, 288(%rdi) -vpxor 192(%rdi), %ymm4, %ymm8 -vpxor 704(%rdi), %ymm3, %ymm9 -vpxor 416(%rdi), %ymm2, %ymm10 -vpxor 128(%rdi), %ymm1, %ymm11 -vpxor 480(%rdi), %ymm5, %ymm12 -vpsllq $1, %ymm8, %ymm13 -vpsllq $6, %ymm9, %ymm14 -vpsllq $25, %ymm10, %ymm15 -#vpsllq $8, %ymm11, %ymm7 -vpsllq $18, %ymm12, %ymm6 -vpsrlq $63, %ymm8, %ymm8 -vpsrlq $58, %ymm9, %ymm9 -vpsrlq $39, %ymm10, %ymm10 -#vpsrlq $56, %ymm11, %ymm11 -vpsrlq $46, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -#vpor %ymm7, %ymm11, %ymm11 -vpshufb %ymm0, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 480(%rdi) -vmovdqa %ymm14, 192(%rdi) -vmovdqa %ymm15, 704(%rdi) -vmovdqa %ymm7, 416(%rdi) -vmovdqa %ymm6, 128(%rdi) -vpxor 768(%rdi), %ymm1, %ymm8 -vpxor 320(%rdi), %ymm5, %ymm9 -vpxor 32(%rdi), %ymm4, %ymm10 -vpxor 544(%rdi), %ymm3, %ymm11 -vpxor 256(%rdi), %ymm2, %ymm12 -vpsllq $27, %ymm8, %ymm13 -vpsllq $36, %ymm9, %ymm14 -vpsllq $10, %ymm10, %ymm15 -vpsllq $15, %ymm11, %ymm7 -#vpsllq $56, %ymm12, %ymm6 -vpsrlq $37, %ymm8, %ymm8 -vpsrlq $28, %ymm9, %ymm9 -vpsrlq $54, %ymm10, %ymm10 -vpsrlq $49, %ymm11, %ymm11 -#vpsrlq $8, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -#vpor %ymm6, %ymm12, %ymm12 -vpshufb rho56(%rip), %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 320(%rdi) -vmovdqa %ymm14, 32(%rdi) -vmovdqa %ymm15, 544(%rdi) -vmovdqa %ymm7, 256(%rdi) -vmovdqa %ymm6, 768(%rdi) -vpxor 384(%rdi), %ymm3, %ymm8 -vpxor 96(%rdi), %ymm2, %ymm9 -vpxor 608(%rdi), %ymm1, %ymm10 -vpxor 160(%rdi), %ymm5, %ymm11 -vpxor 672(%rdi), %ymm4, %ymm12 -vpsllq $62, %ymm8, %ymm13 -vpsllq $55, %ymm9, %ymm14 -vpsllq $39, %ymm10, %ymm15 -vpsllq $41, %ymm11, %ymm7 -vpsllq $2, %ymm12, %ymm6 -vpsrlq $2, %ymm8, %ymm8 -vpsrlq $9, %ymm9, %ymm9 -vpsrlq $25, %ymm10, %ymm10 -vpsrlq $23, %ymm11, %ymm11 -vpsrlq $62, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 160(%rdi) -vmovdqa %ymm14, 672(%rdi) -vmovdqa %ymm15, 384(%rdi) -vmovdqa %ymm7, 96(%rdi) -vmovdqa %ymm6, 608(%rdi) -vmovdqa 0(%rdi), %ymm8 -vmovdqa 32(%rdi), %ymm9 -vmovdqa 64(%rdi), %ymm10 -vmovdqa 96(%rdi), %ymm11 -vmovdqa 128(%rdi), %ymm12 -vpxor 160(%rdi), %ymm8, %ymm8 -vpxor 192(%rdi), %ymm9, %ymm9 -vpxor 224(%rdi), %ymm10, %ymm10 -vpxor 256(%rdi), %ymm11, %ymm11 -vpxor 288(%rdi), %ymm12, %ymm12 -vpxor 320(%rdi), %ymm8, %ymm8 -vpxor 352(%rdi), %ymm9, %ymm9 -vpxor 384(%rdi), %ymm10, %ymm10 -vpxor 416(%rdi), %ymm11, %ymm11 -vpxor 448(%rdi), %ymm12, %ymm12 -vpxor 480(%rdi), %ymm8, %ymm8 -vpxor 512(%rdi), %ymm9, %ymm9 -vpxor 544(%rdi), %ymm10, %ymm10 -vpxor 576(%rdi), %ymm11, %ymm11 -vpxor 608(%rdi), %ymm12, %ymm12 -vpxor 640(%rdi), %ymm8, %ymm8 -vpxor 672(%rdi), %ymm9, %ymm9 -vpxor 704(%rdi), %ymm10, %ymm10 -vpxor 736(%rdi), %ymm11, %ymm11 -vpxor 768(%rdi), %ymm12, %ymm12 -vpsllq $1, %ymm9, %ymm13 -vpsllq $1, %ymm10, %ymm14 -vpsllq $1, %ymm11, %ymm15 -vpsllq $1, %ymm12, %ymm7 -vpsllq $1, %ymm8, %ymm6 -vpsrlq $63, %ymm9, %ymm5 -vpsrlq $63, %ymm10, %ymm4 -vpsrlq $63, %ymm11, %ymm3 -vpsrlq $63, %ymm12, %ymm2 -vpsrlq $63, %ymm8, %ymm1 -vpor %ymm13, %ymm5, %ymm5 -vpor %ymm14, %ymm4, %ymm4 -vpor %ymm15, %ymm3, %ymm3 -vpor %ymm7, %ymm2, %ymm2 -vpor %ymm6, %ymm1, %ymm1 -vpxor %ymm5, %ymm12, %ymm5 -vpxor %ymm4, %ymm8, %ymm4 -vpxor %ymm3, %ymm9, %ymm3 -vpxor %ymm2, %ymm10, %ymm2 -vpxor %ymm1, %ymm11, %ymm1 -vpxor 0(%rdi), %ymm5, %ymm8 -vpxor 352(%rdi), %ymm4, %ymm9 -vpxor 704(%rdi), %ymm3, %ymm10 -vpxor 256(%rdi), %ymm2, %ymm11 -vpxor 608(%rdi), %ymm1, %ymm12 -vpsllq $44, %ymm9, %ymm14 -vpsllq $43, %ymm10, %ymm15 -vpsllq $21, %ymm11, %ymm7 -vpsllq $14, %ymm12, %ymm6 -vpsrlq $20, %ymm9, %ymm9 -vpsrlq $21, %ymm10, %ymm10 -vpsrlq $43, %ymm11, %ymm11 -vpsrlq $50, %ymm12, %ymm12 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vpbroadcastq 16(%rsi), %ymm8 -vpxor %ymm8, %ymm13, %ymm13 -vmovdqa %ymm13, 0(%rdi) -vmovdqa %ymm14, 352(%rdi) -vmovdqa %ymm15, 704(%rdi) -vmovdqa %ymm7, 256(%rdi) -vmovdqa %ymm6, 608(%rdi) -vpxor 736(%rdi), %ymm2, %ymm8 -vpxor 288(%rdi), %ymm1, %ymm9 -vpxor 480(%rdi), %ymm5, %ymm10 -vpxor 32(%rdi), %ymm4, %ymm11 -vpxor 384(%rdi), %ymm3, %ymm12 -vpsllq $28, %ymm8, %ymm13 -vpsllq $20, %ymm9, %ymm14 -vpsllq $3, %ymm10, %ymm15 -vpsllq $45, %ymm11, %ymm7 -vpsllq $61, %ymm12, %ymm6 -vpsrlq $36, %ymm8, %ymm8 -vpsrlq $44, %ymm9, %ymm9 -vpsrlq $61, %ymm10, %ymm10 -vpsrlq $19, %ymm11, %ymm11 -vpsrlq $3, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 480(%rdi) -vmovdqa %ymm14, 32(%rdi) -vmovdqa %ymm15, 384(%rdi) -vmovdqa %ymm7, 736(%rdi) -vmovdqa %ymm6, 288(%rdi) -vpxor 512(%rdi), %ymm4, %ymm8 -vpxor 64(%rdi), %ymm3, %ymm9 -vpxor 416(%rdi), %ymm2, %ymm10 -vpxor 768(%rdi), %ymm1, %ymm11 -vpxor 160(%rdi), %ymm5, %ymm12 -vpsllq $1, %ymm8, %ymm13 -vpsllq $6, %ymm9, %ymm14 -vpsllq $25, %ymm10, %ymm15 -#vpsllq $8, %ymm11, %ymm7 -vpsllq $18, %ymm12, %ymm6 -vpsrlq $63, %ymm8, %ymm8 -vpsrlq $58, %ymm9, %ymm9 -vpsrlq $39, %ymm10, %ymm10 -#vpsrlq $56, %ymm11, %ymm11 -vpsrlq $46, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -#vpor %ymm7, %ymm11, %ymm11 -vpshufb %ymm0, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 160(%rdi) -vmovdqa %ymm14, 512(%rdi) -vmovdqa %ymm15, 64(%rdi) -vmovdqa %ymm7, 416(%rdi) -vmovdqa %ymm6, 768(%rdi) -vpxor 448(%rdi), %ymm1, %ymm8 -vpxor 640(%rdi), %ymm5, %ymm9 -vpxor 192(%rdi), %ymm4, %ymm10 -vpxor 544(%rdi), %ymm3, %ymm11 -vpxor 96(%rdi), %ymm2, %ymm12 -vpsllq $27, %ymm8, %ymm13 -vpsllq $36, %ymm9, %ymm14 -vpsllq $10, %ymm10, %ymm15 -vpsllq $15, %ymm11, %ymm7 -#vpsllq $56, %ymm12, %ymm6 -vpsrlq $37, %ymm8, %ymm8 -vpsrlq $28, %ymm9, %ymm9 -vpsrlq $54, %ymm10, %ymm10 -vpsrlq $49, %ymm11, %ymm11 -#vpsrlq $8, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -#vpor %ymm6, %ymm12, %ymm12 -vpshufb rho56(%rip), %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 640(%rdi) -vmovdqa %ymm14, 192(%rdi) -vmovdqa %ymm15, 544(%rdi) -vmovdqa %ymm7, 96(%rdi) -vmovdqa %ymm6, 448(%rdi) -vpxor 224(%rdi), %ymm3, %ymm8 -vpxor 576(%rdi), %ymm2, %ymm9 -vpxor 128(%rdi), %ymm1, %ymm10 -vpxor 320(%rdi), %ymm5, %ymm11 -vpxor 672(%rdi), %ymm4, %ymm12 -vpsllq $62, %ymm8, %ymm13 -vpsllq $55, %ymm9, %ymm14 -vpsllq $39, %ymm10, %ymm15 -vpsllq $41, %ymm11, %ymm7 -vpsllq $2, %ymm12, %ymm6 -vpsrlq $2, %ymm8, %ymm8 -vpsrlq $9, %ymm9, %ymm9 -vpsrlq $25, %ymm10, %ymm10 -vpsrlq $23, %ymm11, %ymm11 -vpsrlq $62, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 320(%rdi) -vmovdqa %ymm14, 672(%rdi) -vmovdqa %ymm15, 224(%rdi) -vmovdqa %ymm7, 576(%rdi) -vmovdqa %ymm6, 128(%rdi) -vmovdqa 0(%rdi), %ymm8 -vmovdqa 32(%rdi), %ymm9 -vmovdqa 64(%rdi), %ymm10 -vmovdqa 96(%rdi), %ymm11 -vmovdqa 128(%rdi), %ymm12 -vpxor 160(%rdi), %ymm8, %ymm8 -vpxor 192(%rdi), %ymm9, %ymm9 -vpxor 224(%rdi), %ymm10, %ymm10 -vpxor 256(%rdi), %ymm11, %ymm11 -vpxor 288(%rdi), %ymm12, %ymm12 -vpxor 320(%rdi), %ymm8, %ymm8 -vpxor 352(%rdi), %ymm9, %ymm9 -vpxor 384(%rdi), %ymm10, %ymm10 -vpxor 416(%rdi), %ymm11, %ymm11 -vpxor 448(%rdi), %ymm12, %ymm12 -vpxor 480(%rdi), %ymm8, %ymm8 -vpxor 512(%rdi), %ymm9, %ymm9 -vpxor 544(%rdi), %ymm10, %ymm10 -vpxor 576(%rdi), %ymm11, %ymm11 -vpxor 608(%rdi), %ymm12, %ymm12 -vpxor 640(%rdi), %ymm8, %ymm8 -vpxor 672(%rdi), %ymm9, %ymm9 -vpxor 704(%rdi), %ymm10, %ymm10 -vpxor 736(%rdi), %ymm11, %ymm11 -vpxor 768(%rdi), %ymm12, %ymm12 -vpsllq $1, %ymm9, %ymm13 -vpsllq $1, %ymm10, %ymm14 -vpsllq $1, %ymm11, %ymm15 -vpsllq $1, %ymm12, %ymm7 -vpsllq $1, %ymm8, %ymm6 -vpsrlq $63, %ymm9, %ymm5 -vpsrlq $63, %ymm10, %ymm4 -vpsrlq $63, %ymm11, %ymm3 -vpsrlq $63, %ymm12, %ymm2 -vpsrlq $63, %ymm8, %ymm1 -vpor %ymm13, %ymm5, %ymm5 -vpor %ymm14, %ymm4, %ymm4 -vpor %ymm15, %ymm3, %ymm3 -vpor %ymm7, %ymm2, %ymm2 -vpor %ymm6, %ymm1, %ymm1 -vpxor %ymm5, %ymm12, %ymm5 -vpxor %ymm4, %ymm8, %ymm4 -vpxor %ymm3, %ymm9, %ymm3 -vpxor %ymm2, %ymm10, %ymm2 -vpxor %ymm1, %ymm11, %ymm1 -vpxor 0(%rdi), %ymm5, %ymm8 -vpxor 32(%rdi), %ymm4, %ymm9 -vpxor 64(%rdi), %ymm3, %ymm10 -vpxor 96(%rdi), %ymm2, %ymm11 -vpxor 128(%rdi), %ymm1, %ymm12 -vpsllq $44, %ymm9, %ymm14 -vpsllq $43, %ymm10, %ymm15 -vpsllq $21, %ymm11, %ymm7 -vpsllq $14, %ymm12, %ymm6 -vpsrlq $20, %ymm9, %ymm9 -vpsrlq $21, %ymm10, %ymm10 -vpsrlq $43, %ymm11, %ymm11 -vpsrlq $50, %ymm12, %ymm12 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vpbroadcastq 24(%rsi), %ymm8 -vpxor %ymm8, %ymm13, %ymm13 -vmovdqa %ymm13, 0(%rdi) -vmovdqa %ymm14, 32(%rdi) -vmovdqa %ymm15, 64(%rdi) -vmovdqa %ymm7, 96(%rdi) -vmovdqa %ymm6, 128(%rdi) -vpxor 256(%rdi), %ymm2, %ymm8 -vpxor 288(%rdi), %ymm1, %ymm9 -vpxor 160(%rdi), %ymm5, %ymm10 -vpxor 192(%rdi), %ymm4, %ymm11 -vpxor 224(%rdi), %ymm3, %ymm12 -vpsllq $28, %ymm8, %ymm13 -vpsllq $20, %ymm9, %ymm14 -vpsllq $3, %ymm10, %ymm15 -vpsllq $45, %ymm11, %ymm7 -vpsllq $61, %ymm12, %ymm6 -vpsrlq $36, %ymm8, %ymm8 -vpsrlq $44, %ymm9, %ymm9 -vpsrlq $61, %ymm10, %ymm10 -vpsrlq $19, %ymm11, %ymm11 -vpsrlq $3, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 160(%rdi) -vmovdqa %ymm14, 192(%rdi) -vmovdqa %ymm15, 224(%rdi) -vmovdqa %ymm7, 256(%rdi) -vmovdqa %ymm6, 288(%rdi) -vpxor 352(%rdi), %ymm4, %ymm8 -vpxor 384(%rdi), %ymm3, %ymm9 -vpxor 416(%rdi), %ymm2, %ymm10 -vpxor 448(%rdi), %ymm1, %ymm11 -vpxor 320(%rdi), %ymm5, %ymm12 -vpsllq $1, %ymm8, %ymm13 -vpsllq $6, %ymm9, %ymm14 -vpsllq $25, %ymm10, %ymm15 -#vpsllq $8, %ymm11, %ymm7 -vpsllq $18, %ymm12, %ymm6 -vpsrlq $63, %ymm8, %ymm8 -vpsrlq $58, %ymm9, %ymm9 -vpsrlq $39, %ymm10, %ymm10 -#vpsrlq $56, %ymm11, %ymm11 -vpsrlq $46, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -#vpor %ymm7, %ymm11, %ymm11 -vpshufb %ymm0, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 320(%rdi) -vmovdqa %ymm14, 352(%rdi) -vmovdqa %ymm15, 384(%rdi) -vmovdqa %ymm7, 416(%rdi) -vmovdqa %ymm6, 448(%rdi) -vpxor 608(%rdi), %ymm1, %ymm8 -vpxor 480(%rdi), %ymm5, %ymm9 -vpxor 512(%rdi), %ymm4, %ymm10 -vpxor 544(%rdi), %ymm3, %ymm11 -vpxor 576(%rdi), %ymm2, %ymm12 -vpsllq $27, %ymm8, %ymm13 -vpsllq $36, %ymm9, %ymm14 -vpsllq $10, %ymm10, %ymm15 -vpsllq $15, %ymm11, %ymm7 -#vpsllq $56, %ymm12, %ymm6 -vpsrlq $37, %ymm8, %ymm8 -vpsrlq $28, %ymm9, %ymm9 -vpsrlq $54, %ymm10, %ymm10 -vpsrlq $49, %ymm11, %ymm11 -#vpsrlq $8, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -#vpor %ymm6, %ymm12, %ymm12 -vpshufb rho56(%rip), %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 480(%rdi) -vmovdqa %ymm14, 512(%rdi) -vmovdqa %ymm15, 544(%rdi) -vmovdqa %ymm7, 576(%rdi) -vmovdqa %ymm6, 608(%rdi) -vpxor 704(%rdi), %ymm3, %ymm8 -vpxor 736(%rdi), %ymm2, %ymm9 -vpxor 768(%rdi), %ymm1, %ymm10 -vpxor 640(%rdi), %ymm5, %ymm11 -vpxor 672(%rdi), %ymm4, %ymm12 -vpsllq $62, %ymm8, %ymm13 -vpsllq $55, %ymm9, %ymm14 -vpsllq $39, %ymm10, %ymm15 -vpsllq $41, %ymm11, %ymm7 -vpsllq $2, %ymm12, %ymm6 -vpsrlq $2, %ymm8, %ymm8 -vpsrlq $9, %ymm9, %ymm9 -vpsrlq $25, %ymm10, %ymm10 -vpsrlq $23, %ymm11, %ymm11 -vpsrlq $62, %ymm12, %ymm12 -vpor %ymm13, %ymm8, %ymm8 -vpor %ymm14, %ymm9, %ymm9 -vpor %ymm15, %ymm10, %ymm10 -vpor %ymm7, %ymm11, %ymm11 -vpor %ymm6, %ymm12, %ymm12 -vpandn %ymm10, %ymm9, %ymm13 -vpandn %ymm11, %ymm10, %ymm14 -vpandn %ymm12, %ymm11, %ymm15 -vpandn %ymm8, %ymm12, %ymm7 -vpandn %ymm9, %ymm8, %ymm6 -vpxor %ymm8, %ymm13, %ymm13 -vpxor %ymm9, %ymm14, %ymm14 -vpxor %ymm10, %ymm15, %ymm15 -vpxor %ymm11, %ymm7, %ymm7 -vpxor %ymm12, %ymm6, %ymm6 -vmovdqa %ymm13, 640(%rdi) -vmovdqa %ymm14, 672(%rdi) -vmovdqa %ymm15, 704(%rdi) -vmovdqa %ymm7, 736(%rdi) -vmovdqa %ymm6, 768(%rdi) -addq $32, %rsi -subq $1, %rax -jnz looptop -ret - -.section .note.GNU-stack,"",@progbits diff --git a/dilithium/avx2/fips202.c b/dilithium/avx2/fips202.c deleted file mode 120000 index da2fa42..0000000 --- a/dilithium/avx2/fips202.c +++ /dev/null @@ -1 +0,0 @@ -../ref/fips202.c \ No newline at end of file diff --git a/dilithium/avx2/fips202.h b/dilithium/avx2/fips202.h deleted file mode 100644 index 72fb2c2..0000000 --- a/dilithium/avx2/fips202.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef FIPS202_H -#define FIPS202_H - -#include -#include - -#define SHAKE128_RATE 168 -#define SHAKE256_RATE 136 -#define SHA3_256_RATE 136 -#define SHA3_512_RATE 72 - -#define FIPS202_NAMESPACE(s) pqcrystals_dilithium_fips202_avx2_##s - -typedef struct { - uint64_t s[25]; - unsigned int pos; -} keccak_state; - -#define KeccakF_RoundConstants FIPS202_NAMESPACE(KeccakF_RoundConstants) -extern const uint64_t KeccakF_RoundConstants[]; - -#define shake128_init FIPS202_NAMESPACE(shake128_init) -void shake128_init(keccak_state *state); -#define shake128_absorb FIPS202_NAMESPACE(shake128_absorb) -void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake128_finalize FIPS202_NAMESPACE(shake128_finalize) -void shake128_finalize(keccak_state *state); -#define shake128_squeeze FIPS202_NAMESPACE(shake128_squeeze) -void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state); -#define shake128_absorb_once FIPS202_NAMESPACE(shake128_absorb_once) -void shake128_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake128_squeezeblocks FIPS202_NAMESPACE(shake128_squeezeblocks) -void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); - -#define shake256_init FIPS202_NAMESPACE(shake256_init) -void shake256_init(keccak_state *state); -#define shake256_absorb FIPS202_NAMESPACE(shake256_absorb) -void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake256_finalize FIPS202_NAMESPACE(shake256_finalize) -void shake256_finalize(keccak_state *state); -#define shake256_squeeze FIPS202_NAMESPACE(shake256_squeeze) -void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state); -#define shake256_absorb_once FIPS202_NAMESPACE(shake256_absorb_once) -void shake256_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake256_squeezeblocks FIPS202_NAMESPACE(shake256_squeezeblocks) -void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); - -#define shake128 FIPS202_NAMESPACE(shake128) -void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); -#define shake256 FIPS202_NAMESPACE(shake256) -void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); -#define sha3_256 FIPS202_NAMESPACE(sha3_256) -void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen); -#define sha3_512 FIPS202_NAMESPACE(sha3_512) -void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen); - -#endif diff --git a/dilithium/avx2/fips202x4.c b/dilithium/avx2/fips202x4.c deleted file mode 100644 index 2ffa691..0000000 --- a/dilithium/avx2/fips202x4.c +++ /dev/null @@ -1,196 +0,0 @@ -#include -#include -#include -#include -#include "fips202.h" -#include "fips202x4.h" - -static void keccakx4_absorb_once(__m256i s[25], - unsigned int r, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - size_t inlen, - uint8_t p) -{ - size_t i; - uint64_t pos = 0; - __m256i t, idx; - - for(i = 0; i < 25; ++i) - s[i] = _mm256_setzero_si256(); - - idx = _mm256_set_epi64x((long long)in3, (long long)in2, (long long)in1, (long long)in0); - while(inlen >= r) { - for(i = 0; i < r/8; ++i) { - t = _mm256_i64gather_epi64((long long *)pos, idx, 1); - s[i] = _mm256_xor_si256(s[i], t); - pos += 8; - } - inlen -= r; - - f1600x4(s, KeccakF_RoundConstants); - } - - for(i = 0; i < inlen/8; ++i) { - t = _mm256_i64gather_epi64((long long *)pos, idx, 1); - s[i] = _mm256_xor_si256(s[i], t); - pos += 8; - } - inlen -= 8*i; - - if(inlen) { - t = _mm256_i64gather_epi64((long long *)pos, idx, 1); - idx = _mm256_set1_epi64x((1ULL << (8*inlen)) - 1); - t = _mm256_and_si256(t, idx); - s[i] = _mm256_xor_si256(s[i], t); - } - - t = _mm256_set1_epi64x((uint64_t)p << 8*inlen); - s[i] = _mm256_xor_si256(s[i], t); - t = _mm256_set1_epi64x(1ULL << 63); - s[r/8 - 1] = _mm256_xor_si256(s[r/8 - 1], t); -} - -static void keccakx4_squeezeblocks(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - size_t nblocks, - unsigned int r, - __m256i s[25]) -{ - unsigned int i; - __m128d t; - - while(nblocks > 0) { - f1600x4(s, KeccakF_RoundConstants); - for(i=0; i < r/8; ++i) { - t = _mm_castsi128_pd(_mm256_castsi256_si128(s[i])); - _mm_storel_pd((__attribute__((__may_alias__)) double *)&out0[8*i], t); - _mm_storeh_pd((__attribute__((__may_alias__)) double *)&out1[8*i], t); - t = _mm_castsi128_pd(_mm256_extracti128_si256(s[i],1)); - _mm_storel_pd((__attribute__((__may_alias__)) double *)&out2[8*i], t); - _mm_storeh_pd((__attribute__((__may_alias__)) double *)&out3[8*i], t); - } - - out0 += r; - out1 += r; - out2 += r; - out3 += r; - --nblocks; - } -} - -void shake128x4_absorb_once(keccakx4_state *state, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - size_t inlen) -{ - keccakx4_absorb_once(state->s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); -} - -void shake128x4_squeezeblocks(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - size_t nblocks, - keccakx4_state *state) -{ - keccakx4_squeezeblocks(out0, out1, out2, out3, nblocks, SHAKE128_RATE, state->s); -} - -void shake256x4_absorb_once(keccakx4_state *state, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - size_t inlen) -{ - keccakx4_absorb_once(state->s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); -} - -void shake256x4_squeezeblocks(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - size_t nblocks, - keccakx4_state *state) -{ - keccakx4_squeezeblocks(out0, out1, out2, out3, nblocks, SHAKE256_RATE, state->s); -} - -void shake128x4(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - size_t outlen, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - size_t inlen) -{ - unsigned int i; - size_t nblocks = outlen/SHAKE128_RATE; - uint8_t t[4][SHAKE128_RATE]; - keccakx4_state state; - - shake128x4_absorb_once(&state, in0, in1, in2, in3, inlen); - shake128x4_squeezeblocks(out0, out1, out2, out3, nblocks, &state); - - out0 += nblocks*SHAKE128_RATE; - out1 += nblocks*SHAKE128_RATE; - out2 += nblocks*SHAKE128_RATE; - out3 += nblocks*SHAKE128_RATE; - outlen -= nblocks*SHAKE128_RATE; - - if(outlen) { - shake128x4_squeezeblocks(t[0], t[1], t[2], t[3], 1, &state); - for(i = 0; i < outlen; ++i) { - out0[i] = t[0][i]; - out1[i] = t[1][i]; - out2[i] = t[2][i]; - out3[i] = t[3][i]; - } - } -} - -void shake256x4(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - size_t outlen, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - size_t inlen) -{ - unsigned int i; - size_t nblocks = outlen/SHAKE256_RATE; - uint8_t t[4][SHAKE256_RATE]; - keccakx4_state state; - - shake256x4_absorb_once(&state, in0, in1, in2, in3, inlen); - shake256x4_squeezeblocks(out0, out1, out2, out3, nblocks, &state); - - out0 += nblocks*SHAKE256_RATE; - out1 += nblocks*SHAKE256_RATE; - out2 += nblocks*SHAKE256_RATE; - out3 += nblocks*SHAKE256_RATE; - outlen -= nblocks*SHAKE256_RATE; - - if(outlen) { - shake256x4_squeezeblocks(t[0], t[1], t[2], t[3], 1, &state); - for(i = 0; i < outlen; ++i) { - out0[i] = t[0][i]; - out1[i] = t[1][i]; - out2[i] = t[2][i]; - out3[i] = t[3][i]; - } - } -} diff --git a/dilithium/avx2/fips202x4.h b/dilithium/avx2/fips202x4.h deleted file mode 100644 index 3288a3a..0000000 --- a/dilithium/avx2/fips202x4.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef FIPS202X4_H -#define FIPS202X4_H - -#define FIPS202X4_NAMESPACE(s) pqcrystals_dilithium_fips202x4_avx2_##s - -#ifdef __ASSEMBLER__ -/* The C ABI on MacOS exports all symbols with a leading - * underscore. This means that any symbols we refer to from - * C files (functions) can't be found, and all symbols we - * refer to from ASM also can't be found. - * - * This define helps us get around this - */ -#if defined(__WIN32__) || defined(__APPLE__) -#define decorate(s) _##s -#define _cdecl(s) decorate(s) -#define cdecl(s) _cdecl(FIPS202X4_NAMESPACE(##s)) -#else -#define cdecl(s) FIPS202X4_NAMESPACE(##s) -#endif - -#else -#include -#include -#include - -typedef struct { - __m256i s[25]; -} keccakx4_state; - -#define f1600x4 FIPS202X4_NAMESPACE(f1600x4) -void f1600x4(__m256i *s, const uint64_t *rc); - -#define shake128x4_absorb_once FIPS202X4_NAMESPACE(shake128x4_absorb_once) -void shake128x4_absorb_once(keccakx4_state *state, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - size_t inlen); - -#define shake128x4_squeezeblocks FIPS202X4_NAMESPACE(shake128x4_squeezeblocks) -void shake128x4_squeezeblocks(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - size_t nblocks, - keccakx4_state *state); - -#define shake256x4_absorb_once FIPS202X4_NAMESPACE(shake256x4_absorb_once) -void shake256x4_absorb_once(keccakx4_state *state, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - size_t inlen); - -#define shake256x4_squeezeblocks FIPS202X4_NAMESPACE(shake256x4_squeezeblocks) -void shake256x4_squeezeblocks(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - size_t nblocks, - keccakx4_state *state); - -#define shake128x4 FIPS202X4_NAMESPACE(shake128x4) -void shake128x4(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - size_t outlen, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - size_t inlen); - -#define shake256x4 FIPS202X4_NAMESPACE(shake256x4) -void shake256x4(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - size_t outlen, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - size_t inlen); - -#endif -#endif diff --git a/dilithium/avx2/invntt.S b/dilithium/avx2/invntt.S deleted file mode 100644 index d40ca13..0000000 --- a/dilithium/avx2/invntt.S +++ /dev/null @@ -1,240 +0,0 @@ -#include "consts.h" -.include "shuffle.inc" - -.macro butterfly l,h,zl0=1,zl1=1,zh0=2,zh1=2 -vpsubd %ymm\l,%ymm\h,%ymm12 -vpaddd %ymm\h,%ymm\l,%ymm\l - -vpmuldq %ymm\zl0,%ymm12,%ymm13 -vmovshdup %ymm12,%ymm\h -vpmuldq %ymm\zl1,%ymm\h,%ymm14 - -vpmuldq %ymm\zh0,%ymm12,%ymm12 -vpmuldq %ymm\zh1,%ymm\h,%ymm\h - -vpmuldq %ymm0,%ymm13,%ymm13 -vpmuldq %ymm0,%ymm14,%ymm14 - -vpsubd %ymm13,%ymm12,%ymm12 -vpsubd %ymm14,%ymm\h,%ymm\h - -vmovshdup %ymm12,%ymm12 -vpblendd $0xAA,%ymm\h,%ymm12,%ymm\h -.endm - -.macro levels0t5 off -vmovdqa 256*\off+ 0(%rdi),%ymm4 -vmovdqa 256*\off+ 32(%rdi),%ymm5 -vmovdqa 256*\off+ 64(%rdi),%ymm6 -vmovdqa 256*\off+ 96(%rdi),%ymm7 -vmovdqa 256*\off+128(%rdi),%ymm8 -vmovdqa 256*\off+160(%rdi),%ymm9 -vmovdqa 256*\off+192(%rdi),%ymm10 -vmovdqa 256*\off+224(%rdi),%ymm11 - -/* level 0 */ -vpermq $0x1B,(_ZETAS_QINV+296-8*\off-8)*4(%rsi),%ymm3 -vpermq $0x1B,(_ZETAS+296-8*\off-8)*4(%rsi),%ymm15 -vmovshdup %ymm3,%ymm1 -vmovshdup %ymm15,%ymm2 -butterfly 4,5,1,3,2,15 - -vpermq $0x1B,(_ZETAS_QINV+296-8*\off-40)*4(%rsi),%ymm3 -vpermq $0x1B,(_ZETAS+296-8*\off-40)*4(%rsi),%ymm15 -vmovshdup %ymm3,%ymm1 -vmovshdup %ymm15,%ymm2 -butterfly 6,7,1,3,2,15 - -vpermq $0x1B,(_ZETAS_QINV+296-8*\off-72)*4(%rsi),%ymm3 -vpermq $0x1B,(_ZETAS+296-8*\off-72)*4(%rsi),%ymm15 -vmovshdup %ymm3,%ymm1 -vmovshdup %ymm15,%ymm2 -butterfly 8,9,1,3,2,15 - -vpermq $0x1B,(_ZETAS_QINV+296-8*\off-104)*4(%rsi),%ymm3 -vpermq $0x1B,(_ZETAS+296-8*\off-104)*4(%rsi),%ymm15 -vmovshdup %ymm3,%ymm1 -vmovshdup %ymm15,%ymm2 -butterfly 10,11,1,3,2,15 - -/* level 1 */ -vpermq $0x1B,(_ZETAS_QINV+168-8*\off-8)*4(%rsi),%ymm3 -vpermq $0x1B,(_ZETAS+168-8*\off-8)*4(%rsi),%ymm15 -vmovshdup %ymm3,%ymm1 -vmovshdup %ymm15,%ymm2 -butterfly 4,6,1,3,2,15 -butterfly 5,7,1,3,2,15 - -vpermq $0x1B,(_ZETAS_QINV+168-8*\off-40)*4(%rsi),%ymm3 -vpermq $0x1B,(_ZETAS+168-8*\off-40)*4(%rsi),%ymm15 -vmovshdup %ymm3,%ymm1 -vmovshdup %ymm15,%ymm2 -butterfly 8,10,1,3,2,15 -butterfly 9,11,1,3,2,15 - -/* level 2 */ -vpermq $0x1B,(_ZETAS_QINV+104-8*\off-8)*4(%rsi),%ymm3 -vpermq $0x1B,(_ZETAS+104-8*\off-8)*4(%rsi),%ymm15 -vmovshdup %ymm3,%ymm1 -vmovshdup %ymm15,%ymm2 -butterfly 4,8,1,3,2,15 -butterfly 5,9,1,3,2,15 -butterfly 6,10,1,3,2,15 -butterfly 7,11,1,3,2,15 - -/* level 3 */ -shuffle2 4,5,3,5 -shuffle2 6,7,4,7 -shuffle2 8,9,6,9 -shuffle2 10,11,8,11 - -vpermq $0x1B,(_ZETAS_QINV+72-8*\off-8)*4(%rsi),%ymm1 -vpermq $0x1B,(_ZETAS+72-8*\off-8)*4(%rsi),%ymm2 -butterfly 3,5 -butterfly 4,7 -butterfly 6,9 -butterfly 8,11 - -/* level 4 */ -shuffle4 3,4,10,4 -shuffle4 6,8,3,8 -shuffle4 5,7,6,7 -shuffle4 9,11,5,11 - -vpermq $0x1B,(_ZETAS_QINV+40-8*\off-8)*4(%rsi),%ymm1 -vpermq $0x1B,(_ZETAS+40-8*\off-8)*4(%rsi),%ymm2 -butterfly 10,4 -butterfly 3,8 -butterfly 6,7 -butterfly 5,11 - -/* level 5 */ -shuffle8 10,3,9,3 -shuffle8 6,5,10,5 -shuffle8 4,8,6,8 -shuffle8 7,11,4,11 - -vpbroadcastd (_ZETAS_QINV+7-\off)*4(%rsi),%ymm1 -vpbroadcastd (_ZETAS+7-\off)*4(%rsi),%ymm2 -butterfly 9,3 -butterfly 10,5 -butterfly 6,8 -butterfly 4,11 - -vmovdqa %ymm9,256*\off+ 0(%rdi) -vmovdqa %ymm10,256*\off+ 32(%rdi) -vmovdqa %ymm6,256*\off+ 64(%rdi) -vmovdqa %ymm4,256*\off+ 96(%rdi) -vmovdqa %ymm3,256*\off+128(%rdi) -vmovdqa %ymm5,256*\off+160(%rdi) -vmovdqa %ymm8,256*\off+192(%rdi) -vmovdqa %ymm11,256*\off+224(%rdi) -.endm - -.macro levels6t7 off -vmovdqa 0+32*\off(%rdi),%ymm4 -vmovdqa 128+32*\off(%rdi),%ymm5 -vmovdqa 256+32*\off(%rdi),%ymm6 -vmovdqa 384+32*\off(%rdi),%ymm7 -vmovdqa 512+32*\off(%rdi),%ymm8 -vmovdqa 640+32*\off(%rdi),%ymm9 -vmovdqa 768+32*\off(%rdi),%ymm10 -vmovdqa 896+32*\off(%rdi),%ymm11 - -/* level 6 */ -vpbroadcastd (_ZETAS_QINV+3)*4(%rsi),%ymm1 -vpbroadcastd (_ZETAS+3)*4(%rsi),%ymm2 -butterfly 4,6 -butterfly 5,7 - -vpbroadcastd (_ZETAS_QINV+2)*4(%rsi),%ymm1 -vpbroadcastd (_ZETAS+2)*4(%rsi),%ymm2 -butterfly 8,10 -butterfly 9,11 - -/* level 7 */ -vpbroadcastd (_ZETAS_QINV+0)*4(%rsi),%ymm1 -vpbroadcastd (_ZETAS+0)*4(%rsi),%ymm2 - -butterfly 4,8 -butterfly 5,9 -butterfly 6,10 -butterfly 7,11 - -vmovdqa %ymm8,512+32*\off(%rdi) -vmovdqa %ymm9,640+32*\off(%rdi) -vmovdqa %ymm10,768+32*\off(%rdi) -vmovdqa %ymm11,896+32*\off(%rdi) - -vmovdqa (_8XDIV_QINV)*4(%rsi),%ymm1 -vmovdqa (_8XDIV)*4(%rsi),%ymm2 -vpmuldq %ymm1,%ymm4,%ymm12 -vpmuldq %ymm1,%ymm5,%ymm13 -vmovshdup %ymm4,%ymm8 -vmovshdup %ymm5,%ymm9 -vpmuldq %ymm1,%ymm8,%ymm14 -vpmuldq %ymm1,%ymm9,%ymm15 -vpmuldq %ymm2,%ymm4,%ymm4 -vpmuldq %ymm2,%ymm5,%ymm5 -vpmuldq %ymm2,%ymm8,%ymm8 -vpmuldq %ymm2,%ymm9,%ymm9 -vpmuldq %ymm0,%ymm12,%ymm12 -vpmuldq %ymm0,%ymm13,%ymm13 -vpmuldq %ymm0,%ymm14,%ymm14 -vpmuldq %ymm0,%ymm15,%ymm15 -vpsubd %ymm12,%ymm4,%ymm4 -vpsubd %ymm13,%ymm5,%ymm5 -vpsubd %ymm14,%ymm8,%ymm8 -vpsubd %ymm15,%ymm9,%ymm9 -vmovshdup %ymm4,%ymm4 -vmovshdup %ymm5,%ymm5 -vpblendd $0xAA,%ymm8,%ymm4,%ymm4 -vpblendd $0xAA,%ymm9,%ymm5,%ymm5 - -vpmuldq %ymm1,%ymm6,%ymm12 -vpmuldq %ymm1,%ymm7,%ymm13 -vmovshdup %ymm6,%ymm8 -vmovshdup %ymm7,%ymm9 -vpmuldq %ymm1,%ymm8,%ymm14 -vpmuldq %ymm1,%ymm9,%ymm15 -vpmuldq %ymm2,%ymm6,%ymm6 -vpmuldq %ymm2,%ymm7,%ymm7 -vpmuldq %ymm2,%ymm8,%ymm8 -vpmuldq %ymm2,%ymm9,%ymm9 -vpmuldq %ymm0,%ymm12,%ymm12 -vpmuldq %ymm0,%ymm13,%ymm13 -vpmuldq %ymm0,%ymm14,%ymm14 -vpmuldq %ymm0,%ymm15,%ymm15 -vpsubd %ymm12,%ymm6,%ymm6 -vpsubd %ymm13,%ymm7,%ymm7 -vpsubd %ymm14,%ymm8,%ymm8 -vpsubd %ymm15,%ymm9,%ymm9 -vmovshdup %ymm6,%ymm6 -vmovshdup %ymm7,%ymm7 -vpblendd $0xAA,%ymm8,%ymm6,%ymm6 -vpblendd $0xAA,%ymm9,%ymm7,%ymm7 - -vmovdqa %ymm4, 0+32*\off(%rdi) -vmovdqa %ymm5,128+32*\off(%rdi) -vmovdqa %ymm6,256+32*\off(%rdi) -vmovdqa %ymm7,384+32*\off(%rdi) -.endm - -.text -.global cdecl(invntt_avx) -cdecl(invntt_avx): -vmovdqa _8XQ*4(%rsi),%ymm0 - -levels0t5 0 -levels0t5 1 -levels0t5 2 -levels0t5 3 - -levels6t7 0 -levels6t7 1 -levels6t7 2 -levels6t7 3 - -ret - -.section .note.GNU-stack,"",@progbits diff --git a/dilithium/avx2/ntt.S b/dilithium/avx2/ntt.S deleted file mode 100644 index 026f057..0000000 --- a/dilithium/avx2/ntt.S +++ /dev/null @@ -1,198 +0,0 @@ -#include "consts.h" -.include "shuffle.inc" - -.macro butterfly l,h,zl0=1,zl1=1,zh0=2,zh1=2 -vpmuldq %ymm\zl0,%ymm\h,%ymm13 -vmovshdup %ymm\h,%ymm12 -vpmuldq %ymm\zl1,%ymm12,%ymm14 - -vpmuldq %ymm\zh0,%ymm\h,%ymm\h -vpmuldq %ymm\zh1,%ymm12,%ymm12 - -vpmuldq %ymm0,%ymm13,%ymm13 -vpmuldq %ymm0,%ymm14,%ymm14 - -vmovshdup %ymm\h,%ymm\h -vpblendd $0xAA,%ymm12,%ymm\h,%ymm\h - -vpsubd %ymm\h,%ymm\l,%ymm12 -vpaddd %ymm\h,%ymm\l,%ymm\l - -vmovshdup %ymm13,%ymm13 -vpblendd $0xAA,%ymm14,%ymm13,%ymm13 - -vpaddd %ymm13,%ymm12,%ymm\h -vpsubd %ymm13,%ymm\l,%ymm\l -.endm - -.macro levels0t1 off -/* level 0 */ -vpbroadcastd (_ZETAS_QINV+1)*4(%rsi),%ymm1 -vpbroadcastd (_ZETAS+1)*4(%rsi),%ymm2 - -vmovdqa 0+32*\off(%rdi),%ymm4 -vmovdqa 128+32*\off(%rdi),%ymm5 -vmovdqa 256+32*\off(%rdi),%ymm6 -vmovdqa 384+32*\off(%rdi),%ymm7 -vmovdqa 512+32*\off(%rdi),%ymm8 -vmovdqa 640+32*\off(%rdi),%ymm9 -vmovdqa 768+32*\off(%rdi),%ymm10 -vmovdqa 896+32*\off(%rdi),%ymm11 - -butterfly 4,8 -butterfly 5,9 -butterfly 6,10 -butterfly 7,11 - -/* level 1 */ -vpbroadcastd (_ZETAS_QINV+2)*4(%rsi),%ymm1 -vpbroadcastd (_ZETAS+2)*4(%rsi),%ymm2 -butterfly 4,6 -butterfly 5,7 - -vpbroadcastd (_ZETAS_QINV+3)*4(%rsi),%ymm1 -vpbroadcastd (_ZETAS+3)*4(%rsi),%ymm2 -butterfly 8,10 -butterfly 9,11 - -vmovdqa %ymm4, 0+32*\off(%rdi) -vmovdqa %ymm5,128+32*\off(%rdi) -vmovdqa %ymm6,256+32*\off(%rdi) -vmovdqa %ymm7,384+32*\off(%rdi) -vmovdqa %ymm8,512+32*\off(%rdi) -vmovdqa %ymm9,640+32*\off(%rdi) -vmovdqa %ymm10,768+32*\off(%rdi) -vmovdqa %ymm11,896+32*\off(%rdi) -.endm - -.macro levels2t7 off -/* level 2 */ -vmovdqa 256*\off+ 0(%rdi),%ymm4 -vmovdqa 256*\off+ 32(%rdi),%ymm5 -vmovdqa 256*\off+ 64(%rdi),%ymm6 -vmovdqa 256*\off+ 96(%rdi),%ymm7 -vmovdqa 256*\off+128(%rdi),%ymm8 -vmovdqa 256*\off+160(%rdi),%ymm9 -vmovdqa 256*\off+192(%rdi),%ymm10 -vmovdqa 256*\off+224(%rdi),%ymm11 - -vpbroadcastd (_ZETAS_QINV+4+\off)*4(%rsi),%ymm1 -vpbroadcastd (_ZETAS+4+\off)*4(%rsi),%ymm2 - -butterfly 4,8 -butterfly 5,9 -butterfly 6,10 -butterfly 7,11 - -shuffle8 4,8,3,8 -shuffle8 5,9,4,9 -shuffle8 6,10,5,10 -shuffle8 7,11,6,11 - -/* level 3 */ -vmovdqa (_ZETAS_QINV+8+8*\off)*4(%rsi),%ymm1 -vmovdqa (_ZETAS+8+8*\off)*4(%rsi),%ymm2 - -butterfly 3,5 -butterfly 8,10 -butterfly 4,6 -butterfly 9,11 - -shuffle4 3,5,7,5 -shuffle4 8,10,3,10 -shuffle4 4,6,8,6 -shuffle4 9,11,4,11 - -/* level 4 */ -vmovdqa (_ZETAS_QINV+40+8*\off)*4(%rsi),%ymm1 -vmovdqa (_ZETAS+40+8*\off)*4(%rsi),%ymm2 - -butterfly 7,8 -butterfly 5,6 -butterfly 3,4 -butterfly 10,11 - -shuffle2 7,8,9,8 -shuffle2 5,6,7,6 -shuffle2 3,4,5,4 -shuffle2 10,11,3,11 - -/* level 5 */ -vmovdqa (_ZETAS_QINV+72+8*\off)*4(%rsi),%ymm1 -vmovdqa (_ZETAS+72+8*\off)*4(%rsi),%ymm2 -vpsrlq $32,%ymm1,%ymm10 -vmovshdup %ymm2,%ymm15 - -butterfly 9,5,1,10,2,15 -butterfly 8,4,1,10,2,15 -butterfly 7,3,1,10,2,15 -butterfly 6,11,1,10,2,15 - -/* level 6 */ -vmovdqa (_ZETAS_QINV+104+8*\off)*4(%rsi),%ymm1 -vmovdqa (_ZETAS+104+8*\off)*4(%rsi),%ymm2 -vpsrlq $32,%ymm1,%ymm10 -vmovshdup %ymm2,%ymm15 -butterfly 9,7,1,10,2,15 -butterfly 8,6,1,10,2,15 - -vmovdqa (_ZETAS_QINV+104+8*\off+32)*4(%rsi),%ymm1 -vmovdqa (_ZETAS+104+8*\off+32)*4(%rsi),%ymm2 -vpsrlq $32,%ymm1,%ymm10 -vmovshdup %ymm2,%ymm15 -butterfly 5,3,1,10,2,15 -butterfly 4,11,1,10,2,15 - -/* level 7 */ -vmovdqa (_ZETAS_QINV+168+8*\off)*4(%rsi),%ymm1 -vmovdqa (_ZETAS+168+8*\off)*4(%rsi),%ymm2 -vpsrlq $32,%ymm1,%ymm10 -vmovshdup %ymm2,%ymm15 -butterfly 9,8,1,10,2,15 - -vmovdqa (_ZETAS_QINV+168+8*\off+32)*4(%rsi),%ymm1 -vmovdqa (_ZETAS+168+8*\off+32)*4(%rsi),%ymm2 -vpsrlq $32,%ymm1,%ymm10 -vmovshdup %ymm2,%ymm15 -butterfly 7,6,1,10,2,15 - -vmovdqa (_ZETAS_QINV+168+8*\off+64)*4(%rsi),%ymm1 -vmovdqa (_ZETAS+168+8*\off+64)*4(%rsi),%ymm2 -vpsrlq $32,%ymm1,%ymm10 -vmovshdup %ymm2,%ymm15 -butterfly 5,4,1,10,2,15 - -vmovdqa (_ZETAS_QINV+168+8*\off+96)*4(%rsi),%ymm1 -vmovdqa (_ZETAS+168+8*\off+96)*4(%rsi),%ymm2 -vpsrlq $32,%ymm1,%ymm10 -vmovshdup %ymm2,%ymm15 -butterfly 3,11,1,10,2,15 - -vmovdqa %ymm9,256*\off+ 0(%rdi) -vmovdqa %ymm8,256*\off+ 32(%rdi) -vmovdqa %ymm7,256*\off+ 64(%rdi) -vmovdqa %ymm6,256*\off+ 96(%rdi) -vmovdqa %ymm5,256*\off+128(%rdi) -vmovdqa %ymm4,256*\off+160(%rdi) -vmovdqa %ymm3,256*\off+192(%rdi) -vmovdqa %ymm11,256*\off+224(%rdi) -.endm - -.text -.global cdecl(ntt_avx) -cdecl(ntt_avx): -vmovdqa _8XQ*4(%rsi),%ymm0 - -levels0t1 0 -levels0t1 1 -levels0t1 2 -levels0t1 3 - -levels2t7 0 -levels2t7 1 -levels2t7 2 -levels2t7 3 - -ret - -.section .note.GNU-stack,"",@progbits diff --git a/dilithium/avx2/ntt.h b/dilithium/avx2/ntt.h deleted file mode 100644 index 0c4fbdd..0000000 --- a/dilithium/avx2/ntt.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef NTT_H -#define NTT_H - -#include - -#define ntt_avx DILITHIUM_NAMESPACE(ntt_avx) -void ntt_avx(__m256i *a, const __m256i *qdata); -#define invntt_avx DILITHIUM_NAMESPACE(invntt_avx) -void invntt_avx(__m256i *a, const __m256i *qdata); - -#define nttunpack_avx DILITHIUM_NAMESPACE(nttunpack_avx) -void nttunpack_avx(__m256i *a); - -#define pointwise_avx DILITHIUM_NAMESPACE(pointwise_avx) -void pointwise_avx(__m256i *c, const __m256i *a, const __m256i *b, const __m256i *qdata); -#define pointwise_acc_avx DILITHIUM_NAMESPACE(pointwise_acc_avx) -void pointwise_acc_avx(__m256i *c, const __m256i *a, const __m256i *b, const __m256i *qdata); - -#endif diff --git a/dilithium/avx2/packing.c b/dilithium/avx2/packing.c deleted file mode 120000 index e77fac9..0000000 --- a/dilithium/avx2/packing.c +++ /dev/null @@ -1 +0,0 @@ -../ref/packing.c \ No newline at end of file diff --git a/dilithium/avx2/packing.h b/dilithium/avx2/packing.h deleted file mode 120000 index d27a8e9..0000000 --- a/dilithium/avx2/packing.h +++ /dev/null @@ -1 +0,0 @@ -../ref/packing.h \ No newline at end of file diff --git a/dilithium/avx2/params.h b/dilithium/avx2/params.h deleted file mode 120000 index 53133cc..0000000 --- a/dilithium/avx2/params.h +++ /dev/null @@ -1 +0,0 @@ -../ref/params.h \ No newline at end of file diff --git a/dilithium/avx2/pointwise.S b/dilithium/avx2/pointwise.S deleted file mode 100644 index 6b687c7..0000000 --- a/dilithium/avx2/pointwise.S +++ /dev/null @@ -1,213 +0,0 @@ -#include "params.h" -#include "consts.h" - -.text -.global cdecl(pointwise_avx) -cdecl(pointwise_avx): -#consts -vmovdqa _8XQINV*4(%rcx),%ymm0 -vmovdqa _8XQ*4(%rcx),%ymm1 - -xor %eax,%eax -_looptop1: -#load -vmovdqa (%rsi),%ymm2 -vmovdqa 32(%rsi),%ymm4 -vmovdqa 64(%rsi),%ymm6 -vmovdqa (%rdx),%ymm10 -vmovdqa 32(%rdx),%ymm12 -vmovdqa 64(%rdx),%ymm14 -vpsrlq $32,%ymm2,%ymm3 -vpsrlq $32,%ymm4,%ymm5 -vmovshdup %ymm6,%ymm7 -vpsrlq $32,%ymm10,%ymm11 -vpsrlq $32,%ymm12,%ymm13 -vmovshdup %ymm14,%ymm15 - -#mul -vpmuldq %ymm2,%ymm10,%ymm2 -vpmuldq %ymm3,%ymm11,%ymm3 -vpmuldq %ymm4,%ymm12,%ymm4 -vpmuldq %ymm5,%ymm13,%ymm5 -vpmuldq %ymm6,%ymm14,%ymm6 -vpmuldq %ymm7,%ymm15,%ymm7 - -#reduce -vpmuldq %ymm0,%ymm2,%ymm10 -vpmuldq %ymm0,%ymm3,%ymm11 -vpmuldq %ymm0,%ymm4,%ymm12 -vpmuldq %ymm0,%ymm5,%ymm13 -vpmuldq %ymm0,%ymm6,%ymm14 -vpmuldq %ymm0,%ymm7,%ymm15 -vpmuldq %ymm1,%ymm10,%ymm10 -vpmuldq %ymm1,%ymm11,%ymm11 -vpmuldq %ymm1,%ymm12,%ymm12 -vpmuldq %ymm1,%ymm13,%ymm13 -vpmuldq %ymm1,%ymm14,%ymm14 -vpmuldq %ymm1,%ymm15,%ymm15 -vpsubq %ymm10,%ymm2,%ymm2 -vpsubq %ymm11,%ymm3,%ymm3 -vpsubq %ymm12,%ymm4,%ymm4 -vpsubq %ymm13,%ymm5,%ymm5 -vpsubq %ymm14,%ymm6,%ymm6 -vpsubq %ymm15,%ymm7,%ymm7 -vpsrlq $32,%ymm2,%ymm2 -vpsrlq $32,%ymm4,%ymm4 -vmovshdup %ymm6,%ymm6 - -#store -vpblendd $0xAA,%ymm3,%ymm2,%ymm2 -vpblendd $0xAA,%ymm5,%ymm4,%ymm4 -vpblendd $0xAA,%ymm7,%ymm6,%ymm6 -vmovdqa %ymm2,(%rdi) -vmovdqa %ymm4,32(%rdi) -vmovdqa %ymm6,64(%rdi) - -add $96,%rdi -add $96,%rsi -add $96,%rdx -add $1,%eax -cmp $10,%eax -jb _looptop1 - -vmovdqa (%rsi),%ymm2 -vmovdqa 32(%rsi),%ymm4 -vmovdqa (%rdx),%ymm10 -vmovdqa 32(%rdx),%ymm12 -vpsrlq $32,%ymm2,%ymm3 -vpsrlq $32,%ymm4,%ymm5 -vmovshdup %ymm10,%ymm11 -vmovshdup %ymm12,%ymm13 - -#mul -vpmuldq %ymm2,%ymm10,%ymm2 -vpmuldq %ymm3,%ymm11,%ymm3 -vpmuldq %ymm4,%ymm12,%ymm4 -vpmuldq %ymm5,%ymm13,%ymm5 - -#reduce -vpmuldq %ymm0,%ymm2,%ymm10 -vpmuldq %ymm0,%ymm3,%ymm11 -vpmuldq %ymm0,%ymm4,%ymm12 -vpmuldq %ymm0,%ymm5,%ymm13 -vpmuldq %ymm1,%ymm10,%ymm10 -vpmuldq %ymm1,%ymm11,%ymm11 -vpmuldq %ymm1,%ymm12,%ymm12 -vpmuldq %ymm1,%ymm13,%ymm13 -vpsubq %ymm10,%ymm2,%ymm2 -vpsubq %ymm11,%ymm3,%ymm3 -vpsubq %ymm12,%ymm4,%ymm4 -vpsubq %ymm13,%ymm5,%ymm5 -vpsrlq $32,%ymm2,%ymm2 -vmovshdup %ymm4,%ymm4 - -#store -vpblendd $0x55,%ymm2,%ymm3,%ymm2 -vpblendd $0x55,%ymm4,%ymm5,%ymm4 -vmovdqa %ymm2,(%rdi) -vmovdqa %ymm4,32(%rdi) - -ret - -.macro pointwise off -#load -vmovdqa \off(%rsi),%ymm6 -vmovdqa \off+32(%rsi),%ymm8 -vmovdqa \off(%rdx),%ymm10 -vmovdqa \off+32(%rdx),%ymm12 -vpsrlq $32,%ymm6,%ymm7 -vpsrlq $32,%ymm8,%ymm9 -vmovshdup %ymm10,%ymm11 -vmovshdup %ymm12,%ymm13 - -#mul -vpmuldq %ymm6,%ymm10,%ymm6 -vpmuldq %ymm7,%ymm11,%ymm7 -vpmuldq %ymm8,%ymm12,%ymm8 -vpmuldq %ymm9,%ymm13,%ymm9 -.endm - -.macro acc -vpaddq %ymm6,%ymm2,%ymm2 -vpaddq %ymm7,%ymm3,%ymm3 -vpaddq %ymm8,%ymm4,%ymm4 -vpaddq %ymm9,%ymm5,%ymm5 -.endm - -.global cdecl(pointwise_acc_avx) -cdecl(pointwise_acc_avx): -#consts -vmovdqa _8XQINV*4(%rcx),%ymm0 -vmovdqa _8XQ*4(%rcx),%ymm1 - -xor %eax,%eax -_looptop2: -pointwise 0 - -#mov -vmovdqa %ymm6,%ymm2 -vmovdqa %ymm7,%ymm3 -vmovdqa %ymm8,%ymm4 -vmovdqa %ymm9,%ymm5 - -pointwise 1024 -acc - -#if L >= 3 -pointwise 2048 -acc -#endif - -#if L >= 4 -pointwise 3072 -acc -#endif - -#if L >= 5 -pointwise 4096 -acc -#endif - -#if L >= 6 -pointwise 5120 -acc -#endif - -#if L >= 7 -pointwise 6144 -acc -#endif - -#reduce -vpmuldq %ymm0,%ymm2,%ymm6 -vpmuldq %ymm0,%ymm3,%ymm7 -vpmuldq %ymm0,%ymm4,%ymm8 -vpmuldq %ymm0,%ymm5,%ymm9 -vpmuldq %ymm1,%ymm6,%ymm6 -vpmuldq %ymm1,%ymm7,%ymm7 -vpmuldq %ymm1,%ymm8,%ymm8 -vpmuldq %ymm1,%ymm9,%ymm9 -vpsubq %ymm6,%ymm2,%ymm2 -vpsubq %ymm7,%ymm3,%ymm3 -vpsubq %ymm8,%ymm4,%ymm4 -vpsubq %ymm9,%ymm5,%ymm5 -vpsrlq $32,%ymm2,%ymm2 -vmovshdup %ymm4,%ymm4 - -#store -vpblendd $0xAA,%ymm3,%ymm2,%ymm2 -vpblendd $0xAA,%ymm5,%ymm4,%ymm4 - -vmovdqa %ymm2,(%rdi) -vmovdqa %ymm4,32(%rdi) - -add $64,%rsi -add $64,%rdx -add $64,%rdi -add $1,%eax -cmp $16,%eax -jb _looptop2 - -ret - -.section .note.GNU-stack,"",@progbits diff --git a/dilithium/avx2/poly.c b/dilithium/avx2/poly.c deleted file mode 100644 index 340e91d..0000000 --- a/dilithium/avx2/poly.c +++ /dev/null @@ -1,1128 +0,0 @@ -#include -#include -#include -#include "align.h" -#include "params.h" -#include "poly.h" -#include "ntt.h" -#include "rounding.h" -#include "rejsample.h" -#include "consts.h" -#include "symmetric.h" -#include "fips202x4.h" - -#ifdef DBENCH -#include "test/cpucycles.h" -extern const uint64_t timing_overhead; -extern uint64_t *tred, *tadd, *tmul, *tround, *tsample, *tpack; -#define DBENCH_START() uint64_t time = cpucycles() -#define DBENCH_STOP(t) t += cpucycles() - time - timing_overhead -#else -#define DBENCH_START() -#define DBENCH_STOP(t) -#endif - -#define _mm256_blendv_epi32(a,b,mask) \ - _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(a), \ - _mm256_castsi256_ps(b), \ - _mm256_castsi256_ps(mask))) - -/************************************************* -* Name: poly_reduce -* -* Description: Inplace reduction of all coefficients of polynomial to -* representative in [-6283009,6283008]. Assumes input -* coefficients to be at most 2^31 - 2^22 - 1 in absolute value. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_reduce(poly *a) { - unsigned int i; - __m256i f,g; - const __m256i q = _mm256_load_si256(&qdata.vec[_8XQ/8]); - const __m256i off = _mm256_set1_epi32(1<<22); - DBENCH_START(); - - for(i = 0; i < N/8; i++) { - f = _mm256_load_si256(&a->vec[i]); - g = _mm256_add_epi32(f,off); - g = _mm256_srai_epi32(g,23); - g = _mm256_mullo_epi32(g,q); - f = _mm256_sub_epi32(f,g); - _mm256_store_si256(&a->vec[i],f); - } - - DBENCH_STOP(*tred); -} - -/************************************************* -* Name: poly_addq -* -* Description: For all coefficients of in/out polynomial add Q if -* coefficient is negative. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_caddq(poly *a) { - unsigned int i; - __m256i f,g; - const __m256i q = _mm256_load_si256(&qdata.vec[_8XQ/8]); - const __m256i zero = _mm256_setzero_si256(); - DBENCH_START(); - - for(i = 0; i < N/8; i++) { - f = _mm256_load_si256(&a->vec[i]); - g = _mm256_blendv_epi32(zero,q,f); - f = _mm256_add_epi32(f,g); - _mm256_store_si256(&a->vec[i],f); - } - - DBENCH_STOP(*tred); -} - -/************************************************* -* Name: poly_add -* -* Description: Add polynomials. No modular reduction is performed. -* -* Arguments: - poly *c: pointer to output polynomial -* - const poly *a: pointer to first summand -* - const poly *b: pointer to second summand -**************************************************/ -void poly_add(poly *c, const poly *a, const poly *b) { - unsigned int i; - __m256i f,g; - DBENCH_START(); - - for(i = 0; i < N/8; i++) { - f = _mm256_load_si256(&a->vec[i]); - g = _mm256_load_si256(&b->vec[i]); - f = _mm256_add_epi32(f,g); - _mm256_store_si256(&c->vec[i],f); - } - - DBENCH_STOP(*tadd); -} - -/************************************************* -* Name: poly_sub -* -* Description: Subtract polynomials. No modular reduction is -* performed. -* -* Arguments: - poly *c: pointer to output polynomial -* - const poly *a: pointer to first input polynomial -* - const poly *b: pointer to second input polynomial to be -* subtraced from first input polynomial -**************************************************/ -void poly_sub(poly *c, const poly *a, const poly *b) { - unsigned int i; - __m256i f,g; - DBENCH_START(); - - for(i = 0; i < N/8; i++) { - f = _mm256_load_si256(&a->vec[i]); - g = _mm256_load_si256(&b->vec[i]); - f = _mm256_sub_epi32(f,g); - _mm256_store_si256(&c->vec[i],f); - } - - DBENCH_STOP(*tadd); -} - -/************************************************* -* Name: poly_shiftl -* -* Description: Multiply polynomial by 2^D without modular reduction. Assumes -* input coefficients to be less than 2^{31-D} in absolute value. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_shiftl(poly *a) { - unsigned int i; - __m256i f; - DBENCH_START(); - - for(i = 0; i < N/8; i++) { - f = _mm256_load_si256(&a->vec[i]); - f = _mm256_slli_epi32(f,D); - _mm256_store_si256(&a->vec[i],f); - } - - DBENCH_STOP(*tmul); -} - -/************************************************* -* Name: poly_ntt -* -* Description: Inplace forward NTT. Coefficients can grow by up to -* 8*Q in absolute value. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_ntt(poly *a) { - DBENCH_START(); - - ntt_avx(a->vec, qdata.vec); - - DBENCH_STOP(*tmul); -} - -/************************************************* -* Name: poly_invntt_tomont -* -* Description: Inplace inverse NTT and multiplication by 2^{32}. -* Input coefficients need to be less than Q in absolute -* value and output coefficients are again bounded by Q. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_invntt_tomont(poly *a) { - DBENCH_START(); - - invntt_avx(a->vec, qdata.vec); - - DBENCH_STOP(*tmul); -} - -void poly_nttunpack(poly *a) { - DBENCH_START(); - - nttunpack_avx(a->vec); - - DBENCH_STOP(*tmul); -} - -/************************************************* -* Name: poly_pointwise_montgomery -* -* Description: Pointwise multiplication of polynomials in NTT domain -* representation and multiplication of resulting polynomial -* by 2^{-32}. -* -* Arguments: - poly *c: pointer to output polynomial -* - const poly *a: pointer to first input polynomial -* - const poly *b: pointer to second input polynomial -**************************************************/ -void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { - DBENCH_START(); - - pointwise_avx(c->vec, a->vec, b->vec, qdata.vec); - - DBENCH_STOP(*tmul); -} - -/************************************************* -* Name: poly_power2round -* -* Description: For all coefficients c of the input polynomial, -* compute c0, c1 such that c mod^+ Q = c1*2^D + c0 -* with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be -* positive standard representatives. -* -* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 -* - poly *a0: pointer to output polynomial with coefficients c0 -* - const poly *a: pointer to input polynomial -**************************************************/ -void poly_power2round(poly *a1, poly *a0, const poly *a) -{ - DBENCH_START(); - - power2round_avx(a1->vec, a0->vec, a->vec); - - DBENCH_STOP(*tround); -} - -/************************************************* -* Name: poly_decompose -* -* Description: For all coefficients c of the input polynomial, -* compute high and low bits c0, c1 such c mod^+ Q = c1*ALPHA + c0 -* with -ALPHA/2 < c0 <= ALPHA/2 except if c1 = (Q-1)/ALPHA where we -* set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0. -* Assumes coefficients to be positive standard representatives. -* -* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 -* - poly *a0: pointer to output polynomial with coefficients c0 -* - const poly *a: pointer to input polynomial -**************************************************/ -void poly_decompose(poly *a1, poly *a0, const poly *a) -{ - DBENCH_START(); - - decompose_avx(a1->vec, a0->vec, a->vec); - - DBENCH_STOP(*tround); -} - -/************************************************* -* Name: poly_make_hint -* -* Description: Compute hint array. The coefficients of which are the -* indices of the coefficients of the input polynomial -* whose low bits overflow into the high bits. -* -* Arguments: - uint8_t *h: pointer to output hint array (preallocated of length N) -* - const poly *a0: pointer to low part of input polynomial -* - const poly *a1: pointer to high part of input polynomial -* -* Returns number of hints, i.e. length of hint array. -**************************************************/ -unsigned int poly_make_hint(uint8_t hint[N], const poly *a0, const poly *a1) -{ - unsigned int r; - DBENCH_START(); - - r = make_hint_avx(hint, a0->vec, a1->vec); - - DBENCH_STOP(*tround); - return r; -} - -/************************************************* -* Name: poly_use_hint -* -* Description: Use hint polynomial to correct the high bits of a polynomial. -* -* Arguments: - poly *b: pointer to output polynomial with corrected high bits -* - const poly *a: pointer to input polynomial -* - const poly *h: pointer to input hint polynomial -**************************************************/ -void poly_use_hint(poly *b, const poly *a, const poly *h) -{ - DBENCH_START(); - - use_hint_avx(b->vec, a->vec, h->vec); - - DBENCH_STOP(*tround); -} - -/************************************************* -* Name: poly_chknorm -* -* Description: Check infinity norm of polynomial against given bound. -* Assumes input polynomial to be reduced by poly_reduce(). -* -* Arguments: - const poly *a: pointer to polynomial -* - int32_t B: norm bound -* -* Returns 0 if norm is strictly smaller than B <= (Q-1)/8 and 1 otherwise. -**************************************************/ -int poly_chknorm(const poly *a, int32_t B) { - unsigned int i; - int r; - __m256i f,t; - const __m256i bound = _mm256_set1_epi32(B-1); - DBENCH_START(); - - if(B > (Q-1)/8) - return 1; - - t = _mm256_setzero_si256(); - for(i = 0; i < N/8; i++) { - f = _mm256_load_si256(&a->vec[i]); - f = _mm256_abs_epi32(f); - f = _mm256_cmpgt_epi32(f,bound); - t = _mm256_or_si256(t,f); - } - - r = 1 - _mm256_testz_si256(t,t); - DBENCH_STOP(*tsample); - return r; -} - -/************************************************* -* Name: rej_uniform -* -* Description: Sample uniformly random coefficients in [0, Q-1] by -* performing rejection sampling on array of random bytes. -* -* Arguments: - int32_t *a: pointer to output array (allocated) -* - unsigned int len: number of coefficients to be sampled -* - const uint8_t *buf: array of random bytes -* - unsigned int buflen: length of array of random bytes -* -* Returns number of sampled coefficients. Can be smaller than len if not enough -* random bytes were given. -**************************************************/ -static unsigned int rej_uniform(int32_t *a, - unsigned int len, - const uint8_t *buf, - unsigned int buflen) -{ - unsigned int ctr, pos; - uint32_t t; - DBENCH_START(); - - ctr = pos = 0; - while(ctr < len && pos + 3 <= buflen) { - t = buf[pos++]; - t |= (uint32_t)buf[pos++] << 8; - t |= (uint32_t)buf[pos++] << 16; - t &= 0x7FFFFF; - - if(t < Q) - a[ctr++] = t; - } - - DBENCH_STOP(*tsample); - return ctr; -} - -/************************************************* -* Name: poly_uniform -* -* Description: Sample polynomial with uniformly random coefficients -* in [0,Q-1] by performing rejection sampling on the -* output stream of SHAKE256(seed|nonce) -* -* Arguments: - poly *a: pointer to output polynomial -* - const uint8_t seed[]: byte array with seed of length SEEDBYTES -* - uint16_t nonce: 2-byte nonce -**************************************************/ -void poly_uniform_preinit(poly *a, stream128_state *state) -{ - unsigned int ctr; - /* rej_uniform_avx reads up to 8 additional bytes */ - ALIGNED_UINT8(REJ_UNIFORM_BUFLEN+8) buf; - - stream128_squeezeblocks(buf.coeffs, REJ_UNIFORM_NBLOCKS, state); - ctr = rej_uniform_avx(a->coeffs, buf.coeffs); - - while(ctr < N) { - /* length of buf is always divisible by 3; hence, no bytes left */ - stream128_squeezeblocks(buf.coeffs, 1, state); - ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf.coeffs, STREAM128_BLOCKBYTES); - } -} - -void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) -{ - stream128_state state; - stream128_init(&state, seed, nonce); - poly_uniform_preinit(a, &state); -} - -void poly_uniform_4x(poly *a0, - poly *a1, - poly *a2, - poly *a3, - const uint8_t seed[32], - uint16_t nonce0, - uint16_t nonce1, - uint16_t nonce2, - uint16_t nonce3) -{ - unsigned int ctr0, ctr1, ctr2, ctr3; - ALIGNED_UINT8(REJ_UNIFORM_BUFLEN+8) buf[4]; - keccakx4_state state; - __m256i f; - - f = _mm256_loadu_si256((__m256i *)seed); - _mm256_store_si256(buf[0].vec,f); - _mm256_store_si256(buf[1].vec,f); - _mm256_store_si256(buf[2].vec,f); - _mm256_store_si256(buf[3].vec,f); - - buf[0].coeffs[SEEDBYTES+0] = nonce0; - buf[0].coeffs[SEEDBYTES+1] = nonce0 >> 8; - buf[1].coeffs[SEEDBYTES+0] = nonce1; - buf[1].coeffs[SEEDBYTES+1] = nonce1 >> 8; - buf[2].coeffs[SEEDBYTES+0] = nonce2; - buf[2].coeffs[SEEDBYTES+1] = nonce2 >> 8; - buf[3].coeffs[SEEDBYTES+0] = nonce3; - buf[3].coeffs[SEEDBYTES+1] = nonce3 >> 8; - - shake128x4_absorb_once(&state, buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, SEEDBYTES + 2); - shake128x4_squeezeblocks(buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, REJ_UNIFORM_NBLOCKS, &state); - - ctr0 = rej_uniform_avx(a0->coeffs, buf[0].coeffs); - ctr1 = rej_uniform_avx(a1->coeffs, buf[1].coeffs); - ctr2 = rej_uniform_avx(a2->coeffs, buf[2].coeffs); - ctr3 = rej_uniform_avx(a3->coeffs, buf[3].coeffs); - - while(ctr0 < N || ctr1 < N || ctr2 < N || ctr3 < N) { - shake128x4_squeezeblocks(buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, 1, &state); - - ctr0 += rej_uniform(a0->coeffs + ctr0, N - ctr0, buf[0].coeffs, SHAKE128_RATE); - ctr1 += rej_uniform(a1->coeffs + ctr1, N - ctr1, buf[1].coeffs, SHAKE128_RATE); - ctr2 += rej_uniform(a2->coeffs + ctr2, N - ctr2, buf[2].coeffs, SHAKE128_RATE); - ctr3 += rej_uniform(a3->coeffs + ctr3, N - ctr3, buf[3].coeffs, SHAKE128_RATE); - } -} - -/************************************************* -* Name: rej_eta -* -* Description: Sample uniformly random coefficients in [-ETA, ETA] by -* performing rejection sampling on array of random bytes. -* -* Arguments: - int32_t *a: pointer to output array (allocated) -* - unsigned int len: number of coefficients to be sampled -* - const uint8_t *buf: array of random bytes -* - unsigned int buflen: length of array of random bytes -* -* Returns number of sampled coefficients. Can be smaller than len if not enough -* random bytes were given. -**************************************************/ -static unsigned int rej_eta(int32_t *a, - unsigned int len, - const uint8_t *buf, - unsigned int buflen) -{ - unsigned int ctr, pos; - uint32_t t0, t1; - DBENCH_START(); - - ctr = pos = 0; - while(ctr < len && pos < buflen) { - t0 = buf[pos] & 0x0F; - t1 = buf[pos++] >> 4; - -#if ETA == 2 - if(t0 < 15) { - t0 = t0 - (205*t0 >> 10)*5; - a[ctr++] = 2 - t0; - } - if(t1 < 15 && ctr < len) { - t1 = t1 - (205*t1 >> 10)*5; - a[ctr++] = 2 - t1; - } -#elif ETA == 4 - if(t0 < 9) - a[ctr++] = 4 - t0; - if(t1 < 9 && ctr < len) - a[ctr++] = 4 - t1; -#endif - } - - DBENCH_STOP(*tsample); - return ctr; -} - -/************************************************* -* Name: poly_uniform_eta -* -* Description: Sample polynomial with uniformly random coefficients -* in [-ETA,ETA] by performing rejection sampling using the -* output stream of SHAKE256(seed|nonce) -* -* Arguments: - poly *a: pointer to output polynomial -* - const uint8_t seed[]: byte array with seed of length CRHBYTES -* - uint16_t nonce: 2-byte nonce -**************************************************/ -void poly_uniform_eta_preinit(poly *a, stream256_state *state) -{ - unsigned int ctr; - ALIGNED_UINT8(REJ_UNIFORM_ETA_BUFLEN) buf; - - stream256_squeezeblocks(buf.coeffs, REJ_UNIFORM_ETA_NBLOCKS, state); - ctr = rej_eta_avx(a->coeffs, buf.coeffs); - - while(ctr < N) { - stream256_squeezeblocks(buf.coeffs, 1, state); - ctr += rej_eta(a->coeffs + ctr, N - ctr, buf.coeffs, STREAM256_BLOCKBYTES); - } -} - -void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) -{ - stream256_state state; - stream256_init(&state, seed, nonce); - poly_uniform_eta_preinit(a, &state); -} - -void poly_uniform_eta_4x(poly *a0, - poly *a1, - poly *a2, - poly *a3, - const uint8_t seed[64], - uint16_t nonce0, - uint16_t nonce1, - uint16_t nonce2, - uint16_t nonce3) -{ - unsigned int ctr0, ctr1, ctr2, ctr3; - ALIGNED_UINT8(REJ_UNIFORM_ETA_BUFLEN) buf[4]; - - __m256i f; - keccakx4_state state; - - f = _mm256_loadu_si256((__m256i *)&seed[0]); - _mm256_store_si256(&buf[0].vec[0],f); - _mm256_store_si256(&buf[1].vec[0],f); - _mm256_store_si256(&buf[2].vec[0],f); - _mm256_store_si256(&buf[3].vec[0],f); - f = _mm256_loadu_si256((__m256i *)&seed[32]); - _mm256_store_si256(&buf[0].vec[1],f); - _mm256_store_si256(&buf[1].vec[1],f); - _mm256_store_si256(&buf[2].vec[1],f); - _mm256_store_si256(&buf[3].vec[1],f); - - buf[0].coeffs[64] = nonce0; - buf[0].coeffs[65] = nonce0 >> 8; - buf[1].coeffs[64] = nonce1; - buf[1].coeffs[65] = nonce1 >> 8; - buf[2].coeffs[64] = nonce2; - buf[2].coeffs[65] = nonce2 >> 8; - buf[3].coeffs[64] = nonce3; - buf[3].coeffs[65] = nonce3 >> 8; - - shake256x4_absorb_once(&state, buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, 66); - shake256x4_squeezeblocks(buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, REJ_UNIFORM_ETA_NBLOCKS, &state); - - ctr0 = rej_eta_avx(a0->coeffs, buf[0].coeffs); - ctr1 = rej_eta_avx(a1->coeffs, buf[1].coeffs); - ctr2 = rej_eta_avx(a2->coeffs, buf[2].coeffs); - ctr3 = rej_eta_avx(a3->coeffs, buf[3].coeffs); - - while(ctr0 < N || ctr1 < N || ctr2 < N || ctr3 < N) { - shake256x4_squeezeblocks(buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, 1, &state); - - ctr0 += rej_eta(a0->coeffs + ctr0, N - ctr0, buf[0].coeffs, SHAKE256_RATE); - ctr1 += rej_eta(a1->coeffs + ctr1, N - ctr1, buf[1].coeffs, SHAKE256_RATE); - ctr2 += rej_eta(a2->coeffs + ctr2, N - ctr2, buf[2].coeffs, SHAKE256_RATE); - ctr3 += rej_eta(a3->coeffs + ctr3, N - ctr3, buf[3].coeffs, SHAKE256_RATE); - } -} - -/************************************************* -* Name: poly_uniform_gamma1 -* -* Description: Sample polynomial with uniformly random coefficients -* in [-(GAMMA1 - 1), GAMMA1] by unpacking output stream -* of SHAKE256(seed|nonce) -* -* Arguments: - poly *a: pointer to output polynomial -* - const uint8_t seed[]: byte array with seed of length CRHBYTES -* - uint16_t nonce: 16-bit nonce -**************************************************/ -#define POLY_UNIFORM_GAMMA1_NBLOCKS ((POLYZ_PACKEDBYTES+STREAM256_BLOCKBYTES-1)/STREAM256_BLOCKBYTES) -void poly_uniform_gamma1_preinit(poly *a, stream256_state *state) -{ - /* polyz_unpack reads 14 additional bytes */ - ALIGNED_UINT8(POLY_UNIFORM_GAMMA1_NBLOCKS*STREAM256_BLOCKBYTES+14) buf; - stream256_squeezeblocks(buf.coeffs, POLY_UNIFORM_GAMMA1_NBLOCKS, state); - polyz_unpack(a, buf.coeffs); -} - -void poly_uniform_gamma1(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) -{ - stream256_state state; - stream256_init(&state, seed, nonce); - poly_uniform_gamma1_preinit(a, &state); -} - -void poly_uniform_gamma1_4x(poly *a0, - poly *a1, - poly *a2, - poly *a3, - const uint8_t seed[64], - uint16_t nonce0, - uint16_t nonce1, - uint16_t nonce2, - uint16_t nonce3) -{ - ALIGNED_UINT8(POLY_UNIFORM_GAMMA1_NBLOCKS*STREAM256_BLOCKBYTES+14) buf[4]; - keccakx4_state state; - __m256i f; - - f = _mm256_loadu_si256((__m256i *)&seed[0]); - _mm256_store_si256(&buf[0].vec[0],f); - _mm256_store_si256(&buf[1].vec[0],f); - _mm256_store_si256(&buf[2].vec[0],f); - _mm256_store_si256(&buf[3].vec[0],f); - f = _mm256_loadu_si256((__m256i *)&seed[32]); - _mm256_store_si256(&buf[0].vec[1],f); - _mm256_store_si256(&buf[1].vec[1],f); - _mm256_store_si256(&buf[2].vec[1],f); - _mm256_store_si256(&buf[3].vec[1],f); - - buf[0].coeffs[64] = nonce0; - buf[0].coeffs[65] = nonce0 >> 8; - buf[1].coeffs[64] = nonce1; - buf[1].coeffs[65] = nonce1 >> 8; - buf[2].coeffs[64] = nonce2; - buf[2].coeffs[65] = nonce2 >> 8; - buf[3].coeffs[64] = nonce3; - buf[3].coeffs[65] = nonce3 >> 8; - - shake256x4_absorb_once(&state, buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, 66); - shake256x4_squeezeblocks(buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, POLY_UNIFORM_GAMMA1_NBLOCKS, &state); - - polyz_unpack(a0, buf[0].coeffs); - polyz_unpack(a1, buf[1].coeffs); - polyz_unpack(a2, buf[2].coeffs); - polyz_unpack(a3, buf[3].coeffs); -} - -/************************************************* -* Name: challenge -* -* Description: Implementation of H. Samples polynomial with TAU nonzero -* coefficients in {-1,1} using the output stream of -* SHAKE256(seed). -* -* Arguments: - poly *c: pointer to output polynomial -* - const uint8_t mu[]: byte array containing seed of length CTILDEBYTES -**************************************************/ -void poly_challenge(poly * restrict c, const uint8_t seed[CTILDEBYTES]) { - unsigned int i, b, pos; - uint64_t signs; - ALIGNED_UINT8(SHAKE256_RATE) buf; - keccak_state state; - - shake256_init(&state); - shake256_absorb(&state, seed, CTILDEBYTES); - shake256_finalize(&state); - shake256_squeezeblocks(buf.coeffs, 1, &state); - - memcpy(&signs, buf.coeffs, 8); - pos = 8; - - memset(c->vec, 0, sizeof(poly)); - for(i = N-TAU; i < N; ++i) { - do { - if(pos >= SHAKE256_RATE) { - shake256_squeezeblocks(buf.coeffs, 1, &state); - pos = 0; - } - - b = buf.coeffs[pos++]; - } while(b > i); - - c->coeffs[i] = c->coeffs[b]; - c->coeffs[b] = 1 - 2*(signs & 1); - signs >>= 1; - } -} - -/************************************************* -* Name: polyeta_pack -* -* Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYETA_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyeta_pack(uint8_t r[POLYETA_PACKEDBYTES], const poly * restrict a) { - unsigned int i; - uint8_t t[8]; - DBENCH_START(); - -#if ETA == 2 - for(i = 0; i < N/8; ++i) { - t[0] = ETA - a->coeffs[8*i+0]; - t[1] = ETA - a->coeffs[8*i+1]; - t[2] = ETA - a->coeffs[8*i+2]; - t[3] = ETA - a->coeffs[8*i+3]; - t[4] = ETA - a->coeffs[8*i+4]; - t[5] = ETA - a->coeffs[8*i+5]; - t[6] = ETA - a->coeffs[8*i+6]; - t[7] = ETA - a->coeffs[8*i+7]; - - r[3*i+0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); - r[3*i+1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); - r[3*i+2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); - } -#elif ETA == 4 - for(i = 0; i < N/2; ++i) { - t[0] = ETA - a->coeffs[2*i+0]; - t[1] = ETA - a->coeffs[2*i+1]; - r[i] = t[0] | (t[1] << 4); - } -#endif - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyeta_unpack -* -* Description: Unpack polynomial with coefficients in [-ETA,ETA]. -* -* Arguments: - poly *r: pointer to output polynomial -* - const uint8_t *a: byte array with bit-packed polynomial -**************************************************/ -void polyeta_unpack(poly * restrict r, const uint8_t a[POLYETA_PACKEDBYTES]) { - unsigned int i; - DBENCH_START(); - -#if ETA == 2 - for(i = 0; i < N/8; ++i) { - r->coeffs[8*i+0] = (a[3*i+0] >> 0) & 7; - r->coeffs[8*i+1] = (a[3*i+0] >> 3) & 7; - r->coeffs[8*i+2] = ((a[3*i+0] >> 6) | (a[3*i+1] << 2)) & 7; - r->coeffs[8*i+3] = (a[3*i+1] >> 1) & 7; - r->coeffs[8*i+4] = (a[3*i+1] >> 4) & 7; - r->coeffs[8*i+5] = ((a[3*i+1] >> 7) | (a[3*i+2] << 1)) & 7; - r->coeffs[8*i+6] = (a[3*i+2] >> 2) & 7; - r->coeffs[8*i+7] = (a[3*i+2] >> 5) & 7; - - r->coeffs[8*i+0] = ETA - r->coeffs[8*i+0]; - r->coeffs[8*i+1] = ETA - r->coeffs[8*i+1]; - r->coeffs[8*i+2] = ETA - r->coeffs[8*i+2]; - r->coeffs[8*i+3] = ETA - r->coeffs[8*i+3]; - r->coeffs[8*i+4] = ETA - r->coeffs[8*i+4]; - r->coeffs[8*i+5] = ETA - r->coeffs[8*i+5]; - r->coeffs[8*i+6] = ETA - r->coeffs[8*i+6]; - r->coeffs[8*i+7] = ETA - r->coeffs[8*i+7]; - } -#elif ETA == 4 - for(i = 0; i < N/2; ++i) { - r->coeffs[2*i+0] = a[i] & 0x0F; - r->coeffs[2*i+1] = a[i] >> 4; - r->coeffs[2*i+0] = ETA - r->coeffs[2*i+0]; - r->coeffs[2*i+1] = ETA - r->coeffs[2*i+1]; - } -#endif - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyt1_pack -* -* Description: Bit-pack polynomial t1 with coefficients fitting in 10 bits. -* Input coefficients are assumed to be positive standard representatives. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYT1_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyt1_pack(uint8_t r[POLYT1_PACKEDBYTES], const poly * restrict a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N/4; ++i) { - r[5*i+0] = (a->coeffs[4*i+0] >> 0); - r[5*i+1] = (a->coeffs[4*i+0] >> 8) | (a->coeffs[4*i+1] << 2); - r[5*i+2] = (a->coeffs[4*i+1] >> 6) | (a->coeffs[4*i+2] << 4); - r[5*i+3] = (a->coeffs[4*i+2] >> 4) | (a->coeffs[4*i+3] << 6); - r[5*i+4] = (a->coeffs[4*i+3] >> 2); - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyt1_unpack -* -* Description: Unpack polynomial t1 with 10-bit coefficients. -* Output coefficients are positive standard representatives. -* -* Arguments: - poly *r: pointer to output polynomial -* - const uint8_t *a: byte array with bit-packed polynomial -**************************************************/ -void polyt1_unpack(poly * restrict r, const uint8_t a[POLYT1_PACKEDBYTES]) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N/4; ++i) { - r->coeffs[4*i+0] = ((a[5*i+0] >> 0) | ((uint32_t)a[5*i+1] << 8)) & 0x3FF; - r->coeffs[4*i+1] = ((a[5*i+1] >> 2) | ((uint32_t)a[5*i+2] << 6)) & 0x3FF; - r->coeffs[4*i+2] = ((a[5*i+2] >> 4) | ((uint32_t)a[5*i+3] << 4)) & 0x3FF; - r->coeffs[4*i+3] = ((a[5*i+3] >> 6) | ((uint32_t)a[5*i+4] << 2)) & 0x3FF; - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyt0_pack -* -* Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYT0_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyt0_pack(uint8_t r[POLYT0_PACKEDBYTES], const poly * restrict a) { - unsigned int i; - uint32_t t[8]; - DBENCH_START(); - - for(i = 0; i < N/8; ++i) { - t[0] = (1 << (D-1)) - a->coeffs[8*i+0]; - t[1] = (1 << (D-1)) - a->coeffs[8*i+1]; - t[2] = (1 << (D-1)) - a->coeffs[8*i+2]; - t[3] = (1 << (D-1)) - a->coeffs[8*i+3]; - t[4] = (1 << (D-1)) - a->coeffs[8*i+4]; - t[5] = (1 << (D-1)) - a->coeffs[8*i+5]; - t[6] = (1 << (D-1)) - a->coeffs[8*i+6]; - t[7] = (1 << (D-1)) - a->coeffs[8*i+7]; - - r[13*i+ 0] = t[0]; - r[13*i+ 1] = t[0] >> 8; - r[13*i+ 1] |= t[1] << 5; - r[13*i+ 2] = t[1] >> 3; - r[13*i+ 3] = t[1] >> 11; - r[13*i+ 3] |= t[2] << 2; - r[13*i+ 4] = t[2] >> 6; - r[13*i+ 4] |= t[3] << 7; - r[13*i+ 5] = t[3] >> 1; - r[13*i+ 6] = t[3] >> 9; - r[13*i+ 6] |= t[4] << 4; - r[13*i+ 7] = t[4] >> 4; - r[13*i+ 8] = t[4] >> 12; - r[13*i+ 8] |= t[5] << 1; - r[13*i+ 9] = t[5] >> 7; - r[13*i+ 9] |= t[6] << 6; - r[13*i+10] = t[6] >> 2; - r[13*i+11] = t[6] >> 10; - r[13*i+11] |= t[7] << 3; - r[13*i+12] = t[7] >> 5; - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyt0_unpack -* -* Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. -* -* Arguments: - poly *r: pointer to output polynomial -* - const uint8_t *a: byte array with bit-packed polynomial -**************************************************/ -void polyt0_unpack(poly * restrict r, const uint8_t a[POLYT0_PACKEDBYTES]) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N/8; ++i) { - r->coeffs[8*i+0] = a[13*i+0]; - r->coeffs[8*i+0] |= (uint32_t)a[13*i+1] << 8; - r->coeffs[8*i+0] &= 0x1FFF; - - r->coeffs[8*i+1] = a[13*i+1] >> 5; - r->coeffs[8*i+1] |= (uint32_t)a[13*i+2] << 3; - r->coeffs[8*i+1] |= (uint32_t)a[13*i+3] << 11; - r->coeffs[8*i+1] &= 0x1FFF; - - r->coeffs[8*i+2] = a[13*i+3] >> 2; - r->coeffs[8*i+2] |= (uint32_t)a[13*i+4] << 6; - r->coeffs[8*i+2] &= 0x1FFF; - - r->coeffs[8*i+3] = a[13*i+4] >> 7; - r->coeffs[8*i+3] |= (uint32_t)a[13*i+5] << 1; - r->coeffs[8*i+3] |= (uint32_t)a[13*i+6] << 9; - r->coeffs[8*i+3] &= 0x1FFF; - - r->coeffs[8*i+4] = a[13*i+6] >> 4; - r->coeffs[8*i+4] |= (uint32_t)a[13*i+7] << 4; - r->coeffs[8*i+4] |= (uint32_t)a[13*i+8] << 12; - r->coeffs[8*i+4] &= 0x1FFF; - - r->coeffs[8*i+5] = a[13*i+8] >> 1; - r->coeffs[8*i+5] |= (uint32_t)a[13*i+9] << 7; - r->coeffs[8*i+5] &= 0x1FFF; - - r->coeffs[8*i+6] = a[13*i+9] >> 6; - r->coeffs[8*i+6] |= (uint32_t)a[13*i+10] << 2; - r->coeffs[8*i+6] |= (uint32_t)a[13*i+11] << 10; - r->coeffs[8*i+6] &= 0x1FFF; - - r->coeffs[8*i+7] = a[13*i+11] >> 3; - r->coeffs[8*i+7] |= (uint32_t)a[13*i+12] << 5; - r->coeffs[8*i+7] &= 0x1FFF; - - r->coeffs[8*i+0] = (1 << (D-1)) - r->coeffs[8*i+0]; - r->coeffs[8*i+1] = (1 << (D-1)) - r->coeffs[8*i+1]; - r->coeffs[8*i+2] = (1 << (D-1)) - r->coeffs[8*i+2]; - r->coeffs[8*i+3] = (1 << (D-1)) - r->coeffs[8*i+3]; - r->coeffs[8*i+4] = (1 << (D-1)) - r->coeffs[8*i+4]; - r->coeffs[8*i+5] = (1 << (D-1)) - r->coeffs[8*i+5]; - r->coeffs[8*i+6] = (1 << (D-1)) - r->coeffs[8*i+6]; - r->coeffs[8*i+7] = (1 << (D-1)) - r->coeffs[8*i+7]; - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyz_pack -* -* Description: Bit-pack polynomial with coefficients -* in [-(GAMMA1 - 1), GAMMA1]. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYZ_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyz_pack(uint8_t r[POLYZ_PACKEDBYTES], const poly * restrict a) { - unsigned int i; - uint32_t t[4]; - DBENCH_START(); - -#if GAMMA1 == (1 << 17) - for(i = 0; i < N/4; ++i) { - t[0] = GAMMA1 - a->coeffs[4*i+0]; - t[1] = GAMMA1 - a->coeffs[4*i+1]; - t[2] = GAMMA1 - a->coeffs[4*i+2]; - t[3] = GAMMA1 - a->coeffs[4*i+3]; - - r[9*i+0] = t[0]; - r[9*i+1] = t[0] >> 8; - r[9*i+2] = t[0] >> 16; - r[9*i+2] |= t[1] << 2; - r[9*i+3] = t[1] >> 6; - r[9*i+4] = t[1] >> 14; - r[9*i+4] |= t[2] << 4; - r[9*i+5] = t[2] >> 4; - r[9*i+6] = t[2] >> 12; - r[9*i+6] |= t[3] << 6; - r[9*i+7] = t[3] >> 2; - r[9*i+8] = t[3] >> 10; - } -#elif GAMMA1 == (1 << 19) - for(i = 0; i < N/2; ++i) { - t[0] = GAMMA1 - a->coeffs[2*i+0]; - t[1] = GAMMA1 - a->coeffs[2*i+1]; - - r[5*i+0] = t[0]; - r[5*i+1] = t[0] >> 8; - r[5*i+2] = t[0] >> 16; - r[5*i+2] |= t[1] << 4; - r[5*i+3] = t[1] >> 4; - r[5*i+4] = t[1] >> 12; - } -#endif - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyz_unpack -* -* Description: Unpack polynomial z with coefficients -* in [-(GAMMA1 - 1), GAMMA1]. -* -* Arguments: - poly *r: pointer to output polynomial -* - const uint8_t *a: byte array with bit-packed polynomial -**************************************************/ -#if GAMMA1 == (1 << 17) -void polyz_unpack(poly * restrict r, const uint8_t *a) { - unsigned int i; - __m256i f; - const __m256i shufbidx = _mm256_set_epi8(-1, 9, 8, 7,-1, 7, 6, 5,-1, 5, 4, 3,-1, 3, 2, 1, - -1, 8, 7, 6,-1, 6, 5, 4,-1, 4, 3, 2,-1, 2, 1, 0); - const __m256i srlvdidx = _mm256_set_epi32(6,4,2,0,6,4,2,0); - const __m256i mask = _mm256_set1_epi32(0x3FFFF); - const __m256i gamma1 = _mm256_set1_epi32(GAMMA1); - DBENCH_START(); - - for(i = 0; i < N/8; i++) { - f = _mm256_loadu_si256((__m256i *)&a[18*i]); - f = _mm256_permute4x64_epi64(f,0x94); - f = _mm256_shuffle_epi8(f,shufbidx); - f = _mm256_srlv_epi32(f,srlvdidx); - f = _mm256_and_si256(f,mask); - f = _mm256_sub_epi32(gamma1,f); - _mm256_store_si256(&r->vec[i],f); - } - - DBENCH_STOP(*tpack); -} - -#elif GAMMA1 == (1 << 19) -void polyz_unpack(poly * restrict r, const uint8_t *a) { - unsigned int i; - __m256i f; - const __m256i shufbidx = _mm256_set_epi8(-1,11,10, 9,-1, 9, 8, 7,-1, 6, 5, 4,-1, 4, 3, 2, - -1, 9, 8, 7,-1, 7, 6, 5,-1, 4, 3, 2,-1, 2, 1, 0); - const __m256i srlvdidx = _mm256_set1_epi64x((uint64_t)4 << 32); - const __m256i mask = _mm256_set1_epi32(0xFFFFF); - const __m256i gamma1 = _mm256_set1_epi32(GAMMA1); - DBENCH_START(); - - for(i = 0; i < N/8; i++) { - f = _mm256_loadu_si256((__m256i *)&a[20*i]); - f = _mm256_permute4x64_epi64(f,0x94); - f = _mm256_shuffle_epi8(f,shufbidx); - f = _mm256_srlv_epi32(f,srlvdidx); - f = _mm256_and_si256(f,mask); - f = _mm256_sub_epi32(gamma1,f); - _mm256_store_si256(&r->vec[i],f); - } - - DBENCH_STOP(*tpack); -} -#endif - -/************************************************* -* Name: polyw1_pack -* -* Description: Bit-pack polynomial w1 with coefficients in [0,15] or [0,43]. -* Input coefficients are assumed to be positive standard representatives. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYW1_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -#if GAMMA2 == (Q-1)/88 -void polyw1_pack(uint8_t *r, const poly * restrict a) { - unsigned int i; - __m256i f0,f1,f2,f3; - const __m256i shift1 = _mm256_set1_epi16((64 << 8) + 1); - const __m256i shift2 = _mm256_set1_epi32((4096 << 16) + 1); - const __m256i shufdidx1 = _mm256_set_epi32(7,3,6,2,5,1,4,0); - const __m256i shufdidx2 = _mm256_set_epi32(-1,-1,6,5,4,2,1,0); - const __m256i shufbidx = _mm256_set_epi8(-1,-1,-1,-1,14,13,12,10, 9, 8, 6, 5, 4, 2, 1, 0, - -1,-1,-1,-1,14,13,12,10, 9, 8, 6, 5, 4, 2, 1, 0); - DBENCH_START(); - - for(i = 0; i < N/32; i++) { - f0 = _mm256_load_si256(&a->vec[4*i+0]); - f1 = _mm256_load_si256(&a->vec[4*i+1]); - f2 = _mm256_load_si256(&a->vec[4*i+2]); - f3 = _mm256_load_si256(&a->vec[4*i+3]); - f0 = _mm256_packus_epi32(f0,f1); - f1 = _mm256_packus_epi32(f2,f3); - f0 = _mm256_packus_epi16(f0,f1); - f0 = _mm256_maddubs_epi16(f0,shift1); - f0 = _mm256_madd_epi16(f0,shift2); - f0 = _mm256_permutevar8x32_epi32(f0,shufdidx1); - f0 = _mm256_shuffle_epi8(f0,shufbidx); - f0 = _mm256_permutevar8x32_epi32(f0,shufdidx2); - _mm256_storeu_si256((__m256i *)&r[24*i],f0); - } - - DBENCH_STOP(*tpack); -} - -#elif GAMMA2 == (Q-1)/32 -void polyw1_pack(uint8_t *r, const poly * restrict a) { - unsigned int i; - __m256i f0, f1, f2, f3, f4, f5, f6, f7; - const __m256i shift = _mm256_set1_epi16((16 << 8) + 1); - const __m256i shufbidx = _mm256_set_epi8(15,14, 7, 6,13,12, 5, 4,11,10, 3, 2, 9, 8, 1, 0, - 15,14, 7, 6,13,12, 5, 4,11,10, 3, 2, 9, 8, 1, 0); - DBENCH_START(); - - for(i = 0; i < N/64; ++i) { - f0 = _mm256_load_si256(&a->vec[8*i+0]); - f1 = _mm256_load_si256(&a->vec[8*i+1]); - f2 = _mm256_load_si256(&a->vec[8*i+2]); - f3 = _mm256_load_si256(&a->vec[8*i+3]); - f4 = _mm256_load_si256(&a->vec[8*i+4]); - f5 = _mm256_load_si256(&a->vec[8*i+5]); - f6 = _mm256_load_si256(&a->vec[8*i+6]); - f7 = _mm256_load_si256(&a->vec[8*i+7]); - f0 = _mm256_packus_epi32(f0,f1); - f1 = _mm256_packus_epi32(f2,f3); - f2 = _mm256_packus_epi32(f4,f5); - f3 = _mm256_packus_epi32(f6,f7); - f0 = _mm256_packus_epi16(f0,f1); - f1 = _mm256_packus_epi16(f2,f3); - f0 = _mm256_maddubs_epi16(f0,shift); - f1 = _mm256_maddubs_epi16(f1,shift); - f0 = _mm256_packus_epi16(f0,f1); - f0 = _mm256_permute4x64_epi64(f0,0xD8); - f0 = _mm256_shuffle_epi8(f0,shufbidx); - _mm256_storeu_si256((__m256i *)&r[32*i], f0); - } - - DBENCH_STOP(*tpack); -} -#endif diff --git a/dilithium/avx2/poly.h b/dilithium/avx2/poly.h deleted file mode 100644 index 7d93088..0000000 --- a/dilithium/avx2/poly.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef POLY_H -#define POLY_H - -#include -#include "align.h" -#include "params.h" -#include "symmetric.h" - -typedef ALIGNED_INT32(N) poly; - -#define poly_reduce DILITHIUM_NAMESPACE(poly_reduce) -void poly_reduce(poly *a); -#define poly_caddq DILITHIUM_NAMESPACE(poly_caddq) -void poly_caddq(poly *a); - -#define poly_add DILITHIUM_NAMESPACE(poly_add) -void poly_add(poly *c, const poly *a, const poly *b); -#define poly_sub DILITHIUM_NAMESPACE(poly_sub) -void poly_sub(poly *c, const poly *a, const poly *b); -#define poly_shiftl DILITHIUM_NAMESPACE(poly_shiftl) -void poly_shiftl(poly *a); - -#define poly_ntt DILITHIUM_NAMESPACE(poly_ntt) -void poly_ntt(poly *a); -#define poly_invntt_tomont DILITHIUM_NAMESPACE(poly_invntt_tomont) -void poly_invntt_tomont(poly *a); -#define poly_nttunpack DILITHIUM_NAMESPACE(poly_nttunpack) -void poly_nttunpack(poly *a); -#define poly_pointwise_montgomery DILITHIUM_NAMESPACE(poly_pointwise_montgomery) -void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); - -#define poly_power2round DILITHIUM_NAMESPACE(poly_power2round) -void poly_power2round(poly *a1, poly *a0, const poly *a); -#define poly_decompose DILITHIUM_NAMESPACE(poly_decompose) -void poly_decompose(poly *a1, poly *a0, const poly *a); -#define poly_make_hint DILITHIUM_NAMESPACE(poly_make_hint) -unsigned int poly_make_hint(uint8_t hint[N], const poly *a0, const poly *a1); -#define poly_use_hint DILITHIUM_NAMESPACE(poly_use_hint) -void poly_use_hint(poly *b, const poly *a, const poly *h); - -#define poly_chknorm DILITHIUM_NAMESPACE(poly_chknorm) -int poly_chknorm(const poly *a, int32_t B); -#define poly_uniform_preinit DILITHIUM_NAMESPACE(poly_uniform_preinit) -void poly_uniform_preinit(poly *a, stream128_state *state); -#define poly_uniform DILITHIUM_NAMESPACE(poly_uniform) -void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); -#define poly_uniform_eta_preinit DILITHIUM_NAMESPACE(poly_uniform_eta_preinit) -void poly_uniform_eta_preinit(poly *a, stream256_state *state); -#define poly_uniform_eta DILITHIUM_NAMESPACE(poly_uniform_eta) -void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); -#define poly_uniform_gamma1_preinit DILITHIUM_NAMESPACE(poly_uniform_gamma1_preinit) -void poly_uniform_gamma1_preinit(poly *a, stream256_state *state); -#define poly_uniform_gamma1 DILITHIUM_NAMESPACE(poly_uniform_gamma1) -void poly_uniform_gamma1(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); -#define poly_challenge DILITHIUM_NAMESPACE(poly_challenge) -void poly_challenge(poly *c, const uint8_t seed[CTILDEBYTES]); - -#define poly_uniform_4x DILITHIUM_NAMESPACE(poly_uniform_4x) -void poly_uniform_4x(poly *a0, - poly *a1, - poly *a2, - poly *a3, - const uint8_t seed[SEEDBYTES], - uint16_t nonce0, - uint16_t nonce1, - uint16_t nonce2, - uint16_t nonce3); -#define poly_uniform_eta_4x DILITHIUM_NAMESPACE(poly_uniform_eta_4x) -void poly_uniform_eta_4x(poly *a0, - poly *a1, - poly *a2, - poly *a3, - const uint8_t seed[CRHBYTES], - uint16_t nonce0, - uint16_t nonce1, - uint16_t nonce2, - uint16_t nonce3); -#define poly_uniform_gamma1_4x DILITHIUM_NAMESPACE(poly_uniform_gamma1_4x) -void poly_uniform_gamma1_4x(poly *a0, - poly *a1, - poly *a2, - poly *a3, - const uint8_t seed[CRHBYTES], - uint16_t nonce0, - uint16_t nonce1, - uint16_t nonce2, - uint16_t nonce3); - -#define polyeta_pack DILITHIUM_NAMESPACE(polyeta_pack) -void polyeta_pack(uint8_t r[POLYETA_PACKEDBYTES], const poly *a); -#define polyeta_unpack DILITHIUM_NAMESPACE(polyeta_unpack) -void polyeta_unpack(poly *r, const uint8_t a[POLYETA_PACKEDBYTES]); - -#define polyt1_pack DILITHIUM_NAMESPACE(polyt1_pack) -void polyt1_pack(uint8_t r[POLYT1_PACKEDBYTES], const poly *a); -#define polyt1_unpack DILITHIUM_NAMESPACE(polyt1_unpack) -void polyt1_unpack(poly *r, const uint8_t a[POLYT1_PACKEDBYTES]); - -#define polyt0_pack DILITHIUM_NAMESPACE(polyt0_pack) -void polyt0_pack(uint8_t r[POLYT0_PACKEDBYTES], const poly *a); -#define polyt0_unpack DILITHIUM_NAMESPACE(polyt0_unpack) -void polyt0_unpack(poly *r, const uint8_t a[POLYT0_PACKEDBYTES]); - -#define polyz_pack DILITHIUM_NAMESPACE(polyz_pack) -void polyz_pack(uint8_t r[POLYZ_PACKEDBYTES], const poly *a); -#define polyz_unpack DILITHIUM_NAMESPACE(polyz_unpack) -void polyz_unpack(poly *r, const uint8_t *a); - -#define polyw1_pack DILITHIUM_NAMESPACE(polyw1_pack) -void polyw1_pack(uint8_t *r, const poly *a); - -#endif diff --git a/dilithium/avx2/polyvec.c b/dilithium/avx2/polyvec.c deleted file mode 100644 index 0db3514..0000000 --- a/dilithium/avx2/polyvec.c +++ /dev/null @@ -1,588 +0,0 @@ -#include -#include "params.h" -#include "polyvec.h" -#include "poly.h" -#include "ntt.h" -#include "consts.h" - -/************************************************* -* Name: expand_mat -* -* Description: Implementation of ExpandA. Generates matrix A with uniformly -* random coefficients a_{i,j} by performing rejection -* sampling on the output stream of SHAKE128(rho|j|i) -* -* Arguments: - polyvecl mat[K]: output matrix -* - const uint8_t rho[]: byte array containing seed rho -**************************************************/ - -#if K == 4 && L == 4 -void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { - polyvec_matrix_expand_row0(&mat[0], NULL, rho); - polyvec_matrix_expand_row1(&mat[1], NULL, rho); - polyvec_matrix_expand_row2(&mat[2], NULL, rho); - polyvec_matrix_expand_row3(&mat[3], NULL, rho); -} - -void polyvec_matrix_expand_row0(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 0, 1, 2, 3); - poly_nttunpack(&rowa->vec[0]); - poly_nttunpack(&rowa->vec[1]); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); -} - -void polyvec_matrix_expand_row1(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 256, 257, 258, 259); - poly_nttunpack(&rowa->vec[0]); - poly_nttunpack(&rowa->vec[1]); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); -} - -void polyvec_matrix_expand_row2(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 512, 513, 514, 515); - poly_nttunpack(&rowa->vec[0]); - poly_nttunpack(&rowa->vec[1]); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); -} - -void polyvec_matrix_expand_row3(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 768, 769, 770, 771); - poly_nttunpack(&rowa->vec[0]); - poly_nttunpack(&rowa->vec[1]); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); -} - -#elif K == 6 && L == 5 -void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { - polyvecl tmp; - polyvec_matrix_expand_row0(&mat[0], &mat[1], rho); - polyvec_matrix_expand_row1(&mat[1], &mat[2], rho); - polyvec_matrix_expand_row2(&mat[2], &mat[3], rho); - polyvec_matrix_expand_row3(&mat[3], NULL, rho); - polyvec_matrix_expand_row4(&mat[4], &mat[5], rho); - polyvec_matrix_expand_row5(&mat[5], &tmp, rho); -} - -void polyvec_matrix_expand_row0(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 0, 1, 2, 3); - poly_uniform_4x(&rowa->vec[4], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 4, 256, 257, 258); - poly_nttunpack(&rowa->vec[0]); - poly_nttunpack(&rowa->vec[1]); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowb->vec[0]); - poly_nttunpack(&rowb->vec[1]); - poly_nttunpack(&rowb->vec[2]); -} - -void polyvec_matrix_expand_row1(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowb->vec[0], &rowb->vec[1], rho, 259, 260, 512, 513); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowb->vec[0]); - poly_nttunpack(&rowb->vec[1]); -} - -void polyvec_matrix_expand_row2(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[2], &rowa->vec[3], &rowa->vec[4], &rowb->vec[0], rho, 514, 515, 516, 768); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowb->vec[0]); -} - -void polyvec_matrix_expand_row3(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[1], &rowa->vec[2], &rowa->vec[3], &rowa->vec[4], rho, 769, 770, 771, 772); - poly_nttunpack(&rowa->vec[1]); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); -} - -void polyvec_matrix_expand_row4(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 1024, 1025, 1026, 1027); - poly_uniform_4x(&rowa->vec[4], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 1028, 1280, 1281, 1282); - poly_nttunpack(&rowa->vec[0]); - poly_nttunpack(&rowa->vec[1]); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowb->vec[0]); - poly_nttunpack(&rowb->vec[1]); - poly_nttunpack(&rowb->vec[2]); -} - -void polyvec_matrix_expand_row5(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowb->vec[0], &rowb->vec[1], rho, 1283, 1284, 1536, 1537); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); -} - -#elif K == 8 && L == 7 -void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { - polyvec_matrix_expand_row0(&mat[0], &mat[1], rho); - polyvec_matrix_expand_row1(&mat[1], &mat[2], rho); - polyvec_matrix_expand_row2(&mat[2], &mat[3], rho); - polyvec_matrix_expand_row3(&mat[3], NULL, rho); - polyvec_matrix_expand_row4(&mat[4], &mat[5], rho); - polyvec_matrix_expand_row5(&mat[5], &mat[6], rho); - polyvec_matrix_expand_row6(&mat[6], &mat[7], rho); - polyvec_matrix_expand_row7(&mat[7], NULL, rho); -} - -void polyvec_matrix_expand_row0(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 0, 1, 2, 3); - poly_uniform_4x(&rowa->vec[4], &rowa->vec[5], &rowa->vec[6], &rowb->vec[0], rho, 4, 5, 6, 256); - poly_nttunpack(&rowa->vec[0]); - poly_nttunpack(&rowa->vec[1]); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowa->vec[5]); - poly_nttunpack(&rowa->vec[6]); - poly_nttunpack(&rowb->vec[0]); -} - -void polyvec_matrix_expand_row1(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[1], &rowa->vec[2], &rowa->vec[3], &rowa->vec[4], rho, 257, 258, 259, 260); - poly_uniform_4x(&rowa->vec[5], &rowa->vec[6], &rowb->vec[0], &rowb->vec[1], rho, 261, 262, 512, 513); - poly_nttunpack(&rowa->vec[1]); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowa->vec[5]); - poly_nttunpack(&rowa->vec[6]); - poly_nttunpack(&rowb->vec[0]); - poly_nttunpack(&rowb->vec[1]); -} - -void polyvec_matrix_expand_row2(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[2], &rowa->vec[3], &rowa->vec[4], &rowa->vec[5], rho, 514, 515, 516, 517); - poly_uniform_4x(&rowa->vec[6], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 518, 768, 769, 770); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowa->vec[5]); - poly_nttunpack(&rowa->vec[6]); - poly_nttunpack(&rowb->vec[0]); - poly_nttunpack(&rowb->vec[1]); - poly_nttunpack(&rowb->vec[2]); -} - -void polyvec_matrix_expand_row3(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowa->vec[5], &rowa->vec[6], rho, 771, 772, 773, 774); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowa->vec[5]); - poly_nttunpack(&rowa->vec[6]); -} - -void polyvec_matrix_expand_row4(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 1024, 1025, 1026, 1027); - poly_uniform_4x(&rowa->vec[4], &rowa->vec[5], &rowa->vec[6], &rowb->vec[0], rho, 1028, 1029, 1030, 1280); - poly_nttunpack(&rowa->vec[0]); - poly_nttunpack(&rowa->vec[1]); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowa->vec[5]); - poly_nttunpack(&rowa->vec[6]); - poly_nttunpack(&rowb->vec[0]); -} - -void polyvec_matrix_expand_row5(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[1], &rowa->vec[2], &rowa->vec[3], &rowa->vec[4], rho, 1281, 1282, 1283, 1284); - poly_uniform_4x(&rowa->vec[5], &rowa->vec[6], &rowb->vec[0], &rowb->vec[1], rho, 1285, 1286, 1536, 1537); - poly_nttunpack(&rowa->vec[1]); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowa->vec[5]); - poly_nttunpack(&rowa->vec[6]); - poly_nttunpack(&rowb->vec[0]); - poly_nttunpack(&rowb->vec[1]); -} - -void polyvec_matrix_expand_row6(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[2], &rowa->vec[3], &rowa->vec[4], &rowa->vec[5], rho, 1538, 1539, 1540, 1541); - poly_uniform_4x(&rowa->vec[6], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 1542, 1792, 1793, 1794); - poly_nttunpack(&rowa->vec[2]); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowa->vec[5]); - poly_nttunpack(&rowa->vec[6]); - poly_nttunpack(&rowb->vec[0]); - poly_nttunpack(&rowb->vec[1]); - poly_nttunpack(&rowb->vec[2]); -} - -void polyvec_matrix_expand_row7(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { - poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowa->vec[5], &rowa->vec[6], rho, 1795, 1796, 1797, 1798); - poly_nttunpack(&rowa->vec[3]); - poly_nttunpack(&rowa->vec[4]); - poly_nttunpack(&rowa->vec[5]); - poly_nttunpack(&rowa->vec[6]); -} - -#else -#error -#endif - -void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); -} - -/**************************************************************/ -/************ Vectors of polynomials of length L **************/ -/**************************************************************/ - -void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_uniform_eta(&v->vec[i], seed, nonce++); -} - -void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_uniform_gamma1(&v->vec[i], seed, L*nonce + i); -} - -void polyvecl_reduce(polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_reduce(&v->vec[i]); -} - -/************************************************* -* Name: polyvecl_add -* -* Description: Add vectors of polynomials of length L. -* No modular reduction is performed. -* -* Arguments: - polyvecl *w: pointer to output vector -* - const polyvecl *u: pointer to first summand -* - const polyvecl *v: pointer to second summand -**************************************************/ -void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyvecl_ntt -* -* Description: Forward NTT of all polynomials in vector of length L. Output -* coefficients can be up to 16*Q larger than input coefficients. -* -* Arguments: - polyvecl *v: pointer to input/output vector -**************************************************/ -void polyvecl_ntt(polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_ntt(&v->vec[i]); -} - -void polyvecl_invntt_tomont(polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_invntt_tomont(&v->vec[i]); -} - -void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); -} - -/************************************************* -* Name: polyvecl_pointwise_acc_montgomery -* -* Description: Pointwise multiply vectors of polynomials of length L, multiply -* resulting vector by 2^{-32} and add (accumulate) polynomials -* in it. Input/output vectors are in NTT domain representation. -* -* Arguments: - poly *w: output polynomial -* - const polyvecl *u: pointer to first input vector -* - const polyvecl *v: pointer to second input vector -**************************************************/ -void polyvecl_pointwise_acc_montgomery(poly *w, const polyvecl *u, const polyvecl *v) { - pointwise_acc_avx(w->vec, u->vec->vec, v->vec->vec, qdata.vec); -} - -/************************************************* -* Name: polyvecl_chknorm -* -* Description: Check infinity norm of polynomials in vector of length L. -* Assumes input polyvecl to be reduced by polyvecl_reduce(). -* -* Arguments: - const polyvecl *v: pointer to vector -* - int32_t B: norm bound -* -* Returns 0 if norm of all polynomials is strictly smaller than B <= (Q-1)/8 -* and 1 otherwise. -**************************************************/ -int polyvecl_chknorm(const polyvecl *v, int32_t bound) { - unsigned int i; - - for(i = 0; i < L; ++i) - if(poly_chknorm(&v->vec[i], bound)) - return 1; - - return 0; -} - -/**************************************************************/ -/************ Vectors of polynomials of length K **************/ -/**************************************************************/ - -void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_uniform_eta(&v->vec[i], seed, nonce++); -} - -/************************************************* -* Name: polyveck_reduce -* -* Description: Reduce coefficients of polynomials in vector of length K -* to representatives in [-6283009,6283008]. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_reduce(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_reduce(&v->vec[i]); -} - -/************************************************* -* Name: polyveck_caddq -* -* Description: For all coefficients of polynomials in vector of length K -* add Q if coefficient is negative. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_caddq(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_caddq(&v->vec[i]); -} - -/************************************************* -* Name: polyveck_add -* -* Description: Add vectors of polynomials of length K. -* No modular reduction is performed. -* -* Arguments: - polyveck *w: pointer to output vector -* - const polyveck *u: pointer to first summand -* - const polyveck *v: pointer to second summand -**************************************************/ -void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_sub -* -* Description: Subtract vectors of polynomials of length K. -* No modular reduction is performed. -* -* Arguments: - polyveck *w: pointer to output vector -* - const polyveck *u: pointer to first input vector -* - const polyveck *v: pointer to second input vector to be -* subtracted from first input vector -**************************************************/ -void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_shiftl -* -* Description: Multiply vector of polynomials of Length K by 2^D without modular -* reduction. Assumes input coefficients to be less than 2^{31-D}. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_shiftl(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_shiftl(&v->vec[i]); -} - -/************************************************* -* Name: polyveck_ntt -* -* Description: Forward NTT of all polynomials in vector of length K. Output -* coefficients can be up to 16*Q larger than input coefficients. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_ntt(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_ntt(&v->vec[i]); -} - -/************************************************* -* Name: polyveck_invntt_tomont -* -* Description: Inverse NTT and multiplication by 2^{32} of polynomials -* in vector of length K. Input coefficients need to be less -* than 2*Q. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_invntt_tomont(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_invntt_tomont(&v->vec[i]); -} - -void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); -} - -/************************************************* -* Name: polyveck_chknorm -* -* Description: Check infinity norm of polynomials in vector of length K. -* Assumes input polyveck to be reduced by polyveck_reduce(). -* -* Arguments: - const polyveck *v: pointer to vector -* - int32_t B: norm bound -* -* Returns 0 if norm of all polynomials are strictly smaller than B <= (Q-1)/8 -* and 1 otherwise. -**************************************************/ -int polyveck_chknorm(const polyveck *v, int32_t bound) { - unsigned int i; - - for(i = 0; i < K; ++i) - if(poly_chknorm(&v->vec[i], bound)) - return 1; - - return 0; -} - -/************************************************* -* Name: polyveck_power2round -* -* Description: For all coefficients a of polynomials in vector of length K, -* compute a0, a1 such that a mod^+ Q = a1*2^D + a0 -* with -2^{D-1} < a0 <= 2^{D-1}. Assumes coefficients to be -* standard representatives. -* -* Arguments: - polyveck *v1: pointer to output vector of polynomials with -* coefficients a1 -* - polyveck *v0: pointer to output vector of polynomials with -* coefficients a0 -* - const polyveck *v: pointer to input vector -**************************************************/ -void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_power2round(&v1->vec[i], &v0->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_decompose -* -* Description: For all coefficients a of polynomials in vector of length K, -* compute high and low bits a0, a1 such a mod^+ Q = a1*ALPHA + a0 -* with -ALPHA/2 < a0 <= ALPHA/2 except a1 = (Q-1)/ALPHA where we -* set a1 = 0 and -ALPHA/2 <= a0 = a mod Q - Q < 0. -* Assumes coefficients to be standard representatives. -* -* Arguments: - polyveck *v1: pointer to output vector of polynomials with -* coefficients a1 -* - polyveck *v0: pointer to output vector of polynomials with -* coefficients a0 -* - const polyveck *v: pointer to input vector -**************************************************/ -void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_decompose(&v1->vec[i], &v0->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_make_hint -* -* Description: Compute hint vector. -* -* Arguments: - uint8_t *hint: pointer to output hint array -* - const polyveck *v0: pointer to low part of input vector -* - const polyveck *v1: pointer to high part of input vector -* -* Returns number of 1 bits. -**************************************************/ -unsigned int polyveck_make_hint(uint8_t *hint, const polyveck *v0, const polyveck *v1) -{ - unsigned int i, n = 0; - - for(i = 0; i < K; ++i) - n += poly_make_hint(&hint[n], &v0->vec[i], &v1->vec[i]); - - return n; -} - -/************************************************* -* Name: polyveck_use_hint -* -* Description: Use hint vector to correct the high bits of input vector. -* -* Arguments: - polyveck *w: pointer to output vector of polynomials with -* corrected high bits -* - const polyveck *u: pointer to input vector -* - const polyveck *h: pointer to input hint vector -**************************************************/ -void polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_use_hint(&w->vec[i], &u->vec[i], &h->vec[i]); -} - -void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1) { - unsigned int i; - - for(i = 0; i < K; ++i) - polyw1_pack(&r[i*POLYW1_PACKEDBYTES], &w1->vec[i]); -} diff --git a/dilithium/avx2/polyvec.h b/dilithium/avx2/polyvec.h deleted file mode 100644 index 1b6dc87..0000000 --- a/dilithium/avx2/polyvec.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef POLYVEC_H -#define POLYVEC_H - -#include -#include "params.h" -#include "poly.h" - -/* Vectors of polynomials of length L */ -typedef struct { - poly vec[L]; -} polyvecl; - -#define polyvecl_uniform_eta DILITHIUM_NAMESPACE(polyvecl_uniform_eta) -void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define polyvecl_uniform_gamma1 DILITHIUM_NAMESPACE(polyvecl_uniform_gamma1) -void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define polyvecl_reduce DILITHIUM_NAMESPACE(polyvecl_reduce) -void polyvecl_reduce(polyvecl *v); - -#define polyvecl_add DILITHIUM_NAMESPACE(polyvecl_add) -void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v); - -#define polyvecl_ntt DILITHIUM_NAMESPACE(polyvecl_ntt) -void polyvecl_ntt(polyvecl *v); -#define polyvecl_invntt_tomont DILITHIUM_NAMESPACE(polyvecl_invntt_tomont) -void polyvecl_invntt_tomont(polyvecl *v); -#define polyvecl_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyvecl_pointwise_poly_montgomery) -void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v); -#define polyvecl_pointwise_acc_montgomery \ - DILITHIUM_NAMESPACE(polyvecl_pointwise_acc_montgomery) -void polyvecl_pointwise_acc_montgomery(poly *w, - const polyvecl *u, - const polyvecl *v); - -#define polyvecl_chknorm DILITHIUM_NAMESPACE(polyvecl_chknorm) -int polyvecl_chknorm(const polyvecl *v, int32_t B); - -/* Vectors of polynomials of length K */ -typedef struct { - poly vec[K]; -} polyveck; - -#define polyveck_uniform_eta DILITHIUM_NAMESPACE(polyveck_uniform_eta) -void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define polyveck_reduce DILITHIUM_NAMESPACE(polyveck_reduce) -void polyveck_reduce(polyveck *v); -#define polyveck_caddq DILITHIUM_NAMESPACE(polyveck_caddq) -void polyveck_caddq(polyveck *v); - -#define polyveck_add DILITHIUM_NAMESPACE(polyveck_add) -void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v); -#define polyveck_sub DILITHIUM_NAMESPACE(polyveck_sub) -void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v); -#define polyveck_shiftl DILITHIUM_NAMESPACE(polyveck_shiftl) -void polyveck_shiftl(polyveck *v); - -#define polyveck_ntt DILITHIUM_NAMESPACE(polyveck_ntt) -void polyveck_ntt(polyveck *v); -#define polyveck_invntt_tomont DILITHIUM_NAMESPACE(polyveck_invntt_tomont) -void polyveck_invntt_tomont(polyveck *v); -#define polyveck_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyveck_pointwise_poly_montgomery) -void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v); - -#define polyveck_chknorm DILITHIUM_NAMESPACE(polyveck_chknorm) -int polyveck_chknorm(const polyveck *v, int32_t B); - -#define polyveck_power2round DILITHIUM_NAMESPACE(polyveck_power2round) -void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v); -#define polyveck_decompose DILITHIUM_NAMESPACE(polyveck_decompose) -void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v); -#define polyveck_make_hint DILITHIUM_NAMESPACE(polyveck_make_hint) -unsigned int polyveck_make_hint(uint8_t *hint, const polyveck *v0, const polyveck *v1); -#define polyveck_use_hint DILITHIUM_NAMESPACE(polyveck_use_hint) -void polyveck_use_hint(polyveck *w, const polyveck *v, const polyveck *h); - -#define polyveck_pack_w1 DILITHIUM_NAMESPACE(polyveck_pack_w1) -void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1); - -#define polyvec_matrix_expand DILITHIUM_NAMESPACE(polyvec_matrix_expand) -void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); - -#define polyvec_matrix_expand_row0 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row0) -void polyvec_matrix_expand_row0(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); -#define polyvec_matrix_expand_row1 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row1) -void polyvec_matrix_expand_row1(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); -#define polyvec_matrix_expand_row2 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row2) -void polyvec_matrix_expand_row2(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); -#define polyvec_matrix_expand_row3 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row3) -void polyvec_matrix_expand_row3(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); -#define polyvec_matrix_expand_row4 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row4) -void polyvec_matrix_expand_row4(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); -#define polyvec_matrix_expand_row5 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row5) -void polyvec_matrix_expand_row5(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); -#define polyvec_matrix_expand_row6 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row6) -void polyvec_matrix_expand_row6(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); -#define polyvec_matrix_expand_row7 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row7) -void polyvec_matrix_expand_row7(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); - -#define polyvec_matrix_pointwise_montgomery DILITHIUM_NAMESPACE(polyvec_matrix_pointwise_montgomery) -void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v); - -#endif diff --git a/dilithium/avx2/randombytes.c b/dilithium/avx2/randombytes.c deleted file mode 120000 index 59a42a5..0000000 --- a/dilithium/avx2/randombytes.c +++ /dev/null @@ -1 +0,0 @@ -../ref/randombytes.c \ No newline at end of file diff --git a/dilithium/avx2/randombytes.h b/dilithium/avx2/randombytes.h deleted file mode 120000 index 055e443..0000000 --- a/dilithium/avx2/randombytes.h +++ /dev/null @@ -1 +0,0 @@ -../ref/randombytes.h \ No newline at end of file diff --git a/dilithium/avx2/rejsample.c b/dilithium/avx2/rejsample.c deleted file mode 100644 index 8b1dde4..0000000 --- a/dilithium/avx2/rejsample.c +++ /dev/null @@ -1,476 +0,0 @@ -#include -#include -#include "params.h" -#include "rejsample.h" -#include "symmetric.h" - -const uint8_t idxlut[256][8] = { - { 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { 1, 0, 0, 0, 0, 0, 0, 0}, - { 0, 1, 0, 0, 0, 0, 0, 0}, - { 2, 0, 0, 0, 0, 0, 0, 0}, - { 0, 2, 0, 0, 0, 0, 0, 0}, - { 1, 2, 0, 0, 0, 0, 0, 0}, - { 0, 1, 2, 0, 0, 0, 0, 0}, - { 3, 0, 0, 0, 0, 0, 0, 0}, - { 0, 3, 0, 0, 0, 0, 0, 0}, - { 1, 3, 0, 0, 0, 0, 0, 0}, - { 0, 1, 3, 0, 0, 0, 0, 0}, - { 2, 3, 0, 0, 0, 0, 0, 0}, - { 0, 2, 3, 0, 0, 0, 0, 0}, - { 1, 2, 3, 0, 0, 0, 0, 0}, - { 0, 1, 2, 3, 0, 0, 0, 0}, - { 4, 0, 0, 0, 0, 0, 0, 0}, - { 0, 4, 0, 0, 0, 0, 0, 0}, - { 1, 4, 0, 0, 0, 0, 0, 0}, - { 0, 1, 4, 0, 0, 0, 0, 0}, - { 2, 4, 0, 0, 0, 0, 0, 0}, - { 0, 2, 4, 0, 0, 0, 0, 0}, - { 1, 2, 4, 0, 0, 0, 0, 0}, - { 0, 1, 2, 4, 0, 0, 0, 0}, - { 3, 4, 0, 0, 0, 0, 0, 0}, - { 0, 3, 4, 0, 0, 0, 0, 0}, - { 1, 3, 4, 0, 0, 0, 0, 0}, - { 0, 1, 3, 4, 0, 0, 0, 0}, - { 2, 3, 4, 0, 0, 0, 0, 0}, - { 0, 2, 3, 4, 0, 0, 0, 0}, - { 1, 2, 3, 4, 0, 0, 0, 0}, - { 0, 1, 2, 3, 4, 0, 0, 0}, - { 5, 0, 0, 0, 0, 0, 0, 0}, - { 0, 5, 0, 0, 0, 0, 0, 0}, - { 1, 5, 0, 0, 0, 0, 0, 0}, - { 0, 1, 5, 0, 0, 0, 0, 0}, - { 2, 5, 0, 0, 0, 0, 0, 0}, - { 0, 2, 5, 0, 0, 0, 0, 0}, - { 1, 2, 5, 0, 0, 0, 0, 0}, - { 0, 1, 2, 5, 0, 0, 0, 0}, - { 3, 5, 0, 0, 0, 0, 0, 0}, - { 0, 3, 5, 0, 0, 0, 0, 0}, - { 1, 3, 5, 0, 0, 0, 0, 0}, - { 0, 1, 3, 5, 0, 0, 0, 0}, - { 2, 3, 5, 0, 0, 0, 0, 0}, - { 0, 2, 3, 5, 0, 0, 0, 0}, - { 1, 2, 3, 5, 0, 0, 0, 0}, - { 0, 1, 2, 3, 5, 0, 0, 0}, - { 4, 5, 0, 0, 0, 0, 0, 0}, - { 0, 4, 5, 0, 0, 0, 0, 0}, - { 1, 4, 5, 0, 0, 0, 0, 0}, - { 0, 1, 4, 5, 0, 0, 0, 0}, - { 2, 4, 5, 0, 0, 0, 0, 0}, - { 0, 2, 4, 5, 0, 0, 0, 0}, - { 1, 2, 4, 5, 0, 0, 0, 0}, - { 0, 1, 2, 4, 5, 0, 0, 0}, - { 3, 4, 5, 0, 0, 0, 0, 0}, - { 0, 3, 4, 5, 0, 0, 0, 0}, - { 1, 3, 4, 5, 0, 0, 0, 0}, - { 0, 1, 3, 4, 5, 0, 0, 0}, - { 2, 3, 4, 5, 0, 0, 0, 0}, - { 0, 2, 3, 4, 5, 0, 0, 0}, - { 1, 2, 3, 4, 5, 0, 0, 0}, - { 0, 1, 2, 3, 4, 5, 0, 0}, - { 6, 0, 0, 0, 0, 0, 0, 0}, - { 0, 6, 0, 0, 0, 0, 0, 0}, - { 1, 6, 0, 0, 0, 0, 0, 0}, - { 0, 1, 6, 0, 0, 0, 0, 0}, - { 2, 6, 0, 0, 0, 0, 0, 0}, - { 0, 2, 6, 0, 0, 0, 0, 0}, - { 1, 2, 6, 0, 0, 0, 0, 0}, - { 0, 1, 2, 6, 0, 0, 0, 0}, - { 3, 6, 0, 0, 0, 0, 0, 0}, - { 0, 3, 6, 0, 0, 0, 0, 0}, - { 1, 3, 6, 0, 0, 0, 0, 0}, - { 0, 1, 3, 6, 0, 0, 0, 0}, - { 2, 3, 6, 0, 0, 0, 0, 0}, - { 0, 2, 3, 6, 0, 0, 0, 0}, - { 1, 2, 3, 6, 0, 0, 0, 0}, - { 0, 1, 2, 3, 6, 0, 0, 0}, - { 4, 6, 0, 0, 0, 0, 0, 0}, - { 0, 4, 6, 0, 0, 0, 0, 0}, - { 1, 4, 6, 0, 0, 0, 0, 0}, - { 0, 1, 4, 6, 0, 0, 0, 0}, - { 2, 4, 6, 0, 0, 0, 0, 0}, - { 0, 2, 4, 6, 0, 0, 0, 0}, - { 1, 2, 4, 6, 0, 0, 0, 0}, - { 0, 1, 2, 4, 6, 0, 0, 0}, - { 3, 4, 6, 0, 0, 0, 0, 0}, - { 0, 3, 4, 6, 0, 0, 0, 0}, - { 1, 3, 4, 6, 0, 0, 0, 0}, - { 0, 1, 3, 4, 6, 0, 0, 0}, - { 2, 3, 4, 6, 0, 0, 0, 0}, - { 0, 2, 3, 4, 6, 0, 0, 0}, - { 1, 2, 3, 4, 6, 0, 0, 0}, - { 0, 1, 2, 3, 4, 6, 0, 0}, - { 5, 6, 0, 0, 0, 0, 0, 0}, - { 0, 5, 6, 0, 0, 0, 0, 0}, - { 1, 5, 6, 0, 0, 0, 0, 0}, - { 0, 1, 5, 6, 0, 0, 0, 0}, - { 2, 5, 6, 0, 0, 0, 0, 0}, - { 0, 2, 5, 6, 0, 0, 0, 0}, - { 1, 2, 5, 6, 0, 0, 0, 0}, - { 0, 1, 2, 5, 6, 0, 0, 0}, - { 3, 5, 6, 0, 0, 0, 0, 0}, - { 0, 3, 5, 6, 0, 0, 0, 0}, - { 1, 3, 5, 6, 0, 0, 0, 0}, - { 0, 1, 3, 5, 6, 0, 0, 0}, - { 2, 3, 5, 6, 0, 0, 0, 0}, - { 0, 2, 3, 5, 6, 0, 0, 0}, - { 1, 2, 3, 5, 6, 0, 0, 0}, - { 0, 1, 2, 3, 5, 6, 0, 0}, - { 4, 5, 6, 0, 0, 0, 0, 0}, - { 0, 4, 5, 6, 0, 0, 0, 0}, - { 1, 4, 5, 6, 0, 0, 0, 0}, - { 0, 1, 4, 5, 6, 0, 0, 0}, - { 2, 4, 5, 6, 0, 0, 0, 0}, - { 0, 2, 4, 5, 6, 0, 0, 0}, - { 1, 2, 4, 5, 6, 0, 0, 0}, - { 0, 1, 2, 4, 5, 6, 0, 0}, - { 3, 4, 5, 6, 0, 0, 0, 0}, - { 0, 3, 4, 5, 6, 0, 0, 0}, - { 1, 3, 4, 5, 6, 0, 0, 0}, - { 0, 1, 3, 4, 5, 6, 0, 0}, - { 2, 3, 4, 5, 6, 0, 0, 0}, - { 0, 2, 3, 4, 5, 6, 0, 0}, - { 1, 2, 3, 4, 5, 6, 0, 0}, - { 0, 1, 2, 3, 4, 5, 6, 0}, - { 7, 0, 0, 0, 0, 0, 0, 0}, - { 0, 7, 0, 0, 0, 0, 0, 0}, - { 1, 7, 0, 0, 0, 0, 0, 0}, - { 0, 1, 7, 0, 0, 0, 0, 0}, - { 2, 7, 0, 0, 0, 0, 0, 0}, - { 0, 2, 7, 0, 0, 0, 0, 0}, - { 1, 2, 7, 0, 0, 0, 0, 0}, - { 0, 1, 2, 7, 0, 0, 0, 0}, - { 3, 7, 0, 0, 0, 0, 0, 0}, - { 0, 3, 7, 0, 0, 0, 0, 0}, - { 1, 3, 7, 0, 0, 0, 0, 0}, - { 0, 1, 3, 7, 0, 0, 0, 0}, - { 2, 3, 7, 0, 0, 0, 0, 0}, - { 0, 2, 3, 7, 0, 0, 0, 0}, - { 1, 2, 3, 7, 0, 0, 0, 0}, - { 0, 1, 2, 3, 7, 0, 0, 0}, - { 4, 7, 0, 0, 0, 0, 0, 0}, - { 0, 4, 7, 0, 0, 0, 0, 0}, - { 1, 4, 7, 0, 0, 0, 0, 0}, - { 0, 1, 4, 7, 0, 0, 0, 0}, - { 2, 4, 7, 0, 0, 0, 0, 0}, - { 0, 2, 4, 7, 0, 0, 0, 0}, - { 1, 2, 4, 7, 0, 0, 0, 0}, - { 0, 1, 2, 4, 7, 0, 0, 0}, - { 3, 4, 7, 0, 0, 0, 0, 0}, - { 0, 3, 4, 7, 0, 0, 0, 0}, - { 1, 3, 4, 7, 0, 0, 0, 0}, - { 0, 1, 3, 4, 7, 0, 0, 0}, - { 2, 3, 4, 7, 0, 0, 0, 0}, - { 0, 2, 3, 4, 7, 0, 0, 0}, - { 1, 2, 3, 4, 7, 0, 0, 0}, - { 0, 1, 2, 3, 4, 7, 0, 0}, - { 5, 7, 0, 0, 0, 0, 0, 0}, - { 0, 5, 7, 0, 0, 0, 0, 0}, - { 1, 5, 7, 0, 0, 0, 0, 0}, - { 0, 1, 5, 7, 0, 0, 0, 0}, - { 2, 5, 7, 0, 0, 0, 0, 0}, - { 0, 2, 5, 7, 0, 0, 0, 0}, - { 1, 2, 5, 7, 0, 0, 0, 0}, - { 0, 1, 2, 5, 7, 0, 0, 0}, - { 3, 5, 7, 0, 0, 0, 0, 0}, - { 0, 3, 5, 7, 0, 0, 0, 0}, - { 1, 3, 5, 7, 0, 0, 0, 0}, - { 0, 1, 3, 5, 7, 0, 0, 0}, - { 2, 3, 5, 7, 0, 0, 0, 0}, - { 0, 2, 3, 5, 7, 0, 0, 0}, - { 1, 2, 3, 5, 7, 0, 0, 0}, - { 0, 1, 2, 3, 5, 7, 0, 0}, - { 4, 5, 7, 0, 0, 0, 0, 0}, - { 0, 4, 5, 7, 0, 0, 0, 0}, - { 1, 4, 5, 7, 0, 0, 0, 0}, - { 0, 1, 4, 5, 7, 0, 0, 0}, - { 2, 4, 5, 7, 0, 0, 0, 0}, - { 0, 2, 4, 5, 7, 0, 0, 0}, - { 1, 2, 4, 5, 7, 0, 0, 0}, - { 0, 1, 2, 4, 5, 7, 0, 0}, - { 3, 4, 5, 7, 0, 0, 0, 0}, - { 0, 3, 4, 5, 7, 0, 0, 0}, - { 1, 3, 4, 5, 7, 0, 0, 0}, - { 0, 1, 3, 4, 5, 7, 0, 0}, - { 2, 3, 4, 5, 7, 0, 0, 0}, - { 0, 2, 3, 4, 5, 7, 0, 0}, - { 1, 2, 3, 4, 5, 7, 0, 0}, - { 0, 1, 2, 3, 4, 5, 7, 0}, - { 6, 7, 0, 0, 0, 0, 0, 0}, - { 0, 6, 7, 0, 0, 0, 0, 0}, - { 1, 6, 7, 0, 0, 0, 0, 0}, - { 0, 1, 6, 7, 0, 0, 0, 0}, - { 2, 6, 7, 0, 0, 0, 0, 0}, - { 0, 2, 6, 7, 0, 0, 0, 0}, - { 1, 2, 6, 7, 0, 0, 0, 0}, - { 0, 1, 2, 6, 7, 0, 0, 0}, - { 3, 6, 7, 0, 0, 0, 0, 0}, - { 0, 3, 6, 7, 0, 0, 0, 0}, - { 1, 3, 6, 7, 0, 0, 0, 0}, - { 0, 1, 3, 6, 7, 0, 0, 0}, - { 2, 3, 6, 7, 0, 0, 0, 0}, - { 0, 2, 3, 6, 7, 0, 0, 0}, - { 1, 2, 3, 6, 7, 0, 0, 0}, - { 0, 1, 2, 3, 6, 7, 0, 0}, - { 4, 6, 7, 0, 0, 0, 0, 0}, - { 0, 4, 6, 7, 0, 0, 0, 0}, - { 1, 4, 6, 7, 0, 0, 0, 0}, - { 0, 1, 4, 6, 7, 0, 0, 0}, - { 2, 4, 6, 7, 0, 0, 0, 0}, - { 0, 2, 4, 6, 7, 0, 0, 0}, - { 1, 2, 4, 6, 7, 0, 0, 0}, - { 0, 1, 2, 4, 6, 7, 0, 0}, - { 3, 4, 6, 7, 0, 0, 0, 0}, - { 0, 3, 4, 6, 7, 0, 0, 0}, - { 1, 3, 4, 6, 7, 0, 0, 0}, - { 0, 1, 3, 4, 6, 7, 0, 0}, - { 2, 3, 4, 6, 7, 0, 0, 0}, - { 0, 2, 3, 4, 6, 7, 0, 0}, - { 1, 2, 3, 4, 6, 7, 0, 0}, - { 0, 1, 2, 3, 4, 6, 7, 0}, - { 5, 6, 7, 0, 0, 0, 0, 0}, - { 0, 5, 6, 7, 0, 0, 0, 0}, - { 1, 5, 6, 7, 0, 0, 0, 0}, - { 0, 1, 5, 6, 7, 0, 0, 0}, - { 2, 5, 6, 7, 0, 0, 0, 0}, - { 0, 2, 5, 6, 7, 0, 0, 0}, - { 1, 2, 5, 6, 7, 0, 0, 0}, - { 0, 1, 2, 5, 6, 7, 0, 0}, - { 3, 5, 6, 7, 0, 0, 0, 0}, - { 0, 3, 5, 6, 7, 0, 0, 0}, - { 1, 3, 5, 6, 7, 0, 0, 0}, - { 0, 1, 3, 5, 6, 7, 0, 0}, - { 2, 3, 5, 6, 7, 0, 0, 0}, - { 0, 2, 3, 5, 6, 7, 0, 0}, - { 1, 2, 3, 5, 6, 7, 0, 0}, - { 0, 1, 2, 3, 5, 6, 7, 0}, - { 4, 5, 6, 7, 0, 0, 0, 0}, - { 0, 4, 5, 6, 7, 0, 0, 0}, - { 1, 4, 5, 6, 7, 0, 0, 0}, - { 0, 1, 4, 5, 6, 7, 0, 0}, - { 2, 4, 5, 6, 7, 0, 0, 0}, - { 0, 2, 4, 5, 6, 7, 0, 0}, - { 1, 2, 4, 5, 6, 7, 0, 0}, - { 0, 1, 2, 4, 5, 6, 7, 0}, - { 3, 4, 5, 6, 7, 0, 0, 0}, - { 0, 3, 4, 5, 6, 7, 0, 0}, - { 1, 3, 4, 5, 6, 7, 0, 0}, - { 0, 1, 3, 4, 5, 6, 7, 0}, - { 2, 3, 4, 5, 6, 7, 0, 0}, - { 0, 2, 3, 4, 5, 6, 7, 0}, - { 1, 2, 3, 4, 5, 6, 7, 0}, - { 0, 1, 2, 3, 4, 5, 6, 7} -}; - -unsigned int rej_uniform_avx(int32_t * restrict r, const uint8_t buf[REJ_UNIFORM_BUFLEN+8]) -{ - unsigned int ctr, pos; - uint32_t good; - __m256i d, tmp; - const __m256i bound = _mm256_set1_epi32(Q); - const __m256i mask = _mm256_set1_epi32(0x7FFFFF); - const __m256i idx8 = _mm256_set_epi8(-1,15,14,13,-1,12,11,10, - -1, 9, 8, 7,-1, 6, 5, 4, - -1,11,10, 9,-1, 8, 7, 6, - -1, 5, 4, 3,-1, 2, 1, 0); - - ctr = pos = 0; - while(pos <= REJ_UNIFORM_BUFLEN - 24) { - d = _mm256_loadu_si256((__m256i *)&buf[pos]); - d = _mm256_permute4x64_epi64(d, 0x94); - d = _mm256_shuffle_epi8(d, idx8); - d = _mm256_and_si256(d, mask); - pos += 24; - - tmp = _mm256_sub_epi32(d, bound); - good = _mm256_movemask_ps((__m256)tmp); - tmp = _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i *)&idxlut[good])); - d = _mm256_permutevar8x32_epi32(d, tmp); - - _mm256_storeu_si256((__m256i *)&r[ctr], d); - ctr += _mm_popcnt_u32(good); - - if(ctr > N - 8) break; - } - - uint32_t t; - while(ctr < N && pos <= REJ_UNIFORM_BUFLEN - 3) { - t = buf[pos++]; - t |= (uint32_t)buf[pos++] << 8; - t |= (uint32_t)buf[pos++] << 16; - t &= 0x7FFFFF; - - if(t < Q) - r[ctr++] = t; - } - - return ctr; -} - -#if ETA == 2 -unsigned int rej_eta_avx(int32_t * restrict r, const uint8_t buf[REJ_UNIFORM_ETA_BUFLEN]) { - unsigned int ctr, pos; - uint32_t good; - __m256i f0, f1, f2; - __m128i g0, g1; - const __m256i mask = _mm256_set1_epi8(15); - const __m256i eta = _mm256_set1_epi8(ETA); - const __m256i bound = mask; - const __m256i v = _mm256_set1_epi32(-6560); - const __m256i p = _mm256_set1_epi32(5); - - ctr = pos = 0; - while(ctr <= N - 8 && pos <= REJ_UNIFORM_ETA_BUFLEN - 16) { - f0 = _mm256_cvtepu8_epi16(_mm_loadu_si128((__m128i *)&buf[pos])); - f1 = _mm256_slli_epi16(f0,4); - f0 = _mm256_or_si256(f0,f1); - f0 = _mm256_and_si256(f0,mask); - - f1 = _mm256_sub_epi8(f0,bound); - f0 = _mm256_sub_epi8(eta,f0); - good = _mm256_movemask_epi8(f1); - - g0 = _mm256_castsi256_si128(f0); - g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); - g1 = _mm_shuffle_epi8(g0,g1); - f1 = _mm256_cvtepi8_epi32(g1); - f2 = _mm256_mulhrs_epi16(f1,v); - f2 = _mm256_mullo_epi16(f2,p); - f1 = _mm256_add_epi32(f1,f2); - _mm256_storeu_si256((__m256i *)&r[ctr],f1); - ctr += _mm_popcnt_u32(good & 0xFF); - good >>= 8; - pos += 4; - - if(ctr > N - 8) break; - g0 = _mm_bsrli_si128(g0,8); - g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); - g1 = _mm_shuffle_epi8(g0,g1); - f1 = _mm256_cvtepi8_epi32(g1); - f2 = _mm256_mulhrs_epi16(f1,v); - f2 = _mm256_mullo_epi16(f2,p); - f1 = _mm256_add_epi32(f1,f2); - _mm256_storeu_si256((__m256i *)&r[ctr],f1); - ctr += _mm_popcnt_u32(good & 0xFF); - good >>= 8; - pos += 4; - - if(ctr > N - 8) break; - g0 = _mm256_extracti128_si256(f0,1); - g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); - g1 = _mm_shuffle_epi8(g0,g1); - f1 = _mm256_cvtepi8_epi32(g1); - f2 = _mm256_mulhrs_epi16(f1,v); - f2 = _mm256_mullo_epi16(f2,p); - f1 = _mm256_add_epi32(f1,f2); - _mm256_storeu_si256((__m256i *)&r[ctr],f1); - ctr += _mm_popcnt_u32(good & 0xFF); - good >>= 8; - pos += 4; - - if(ctr > N - 8) break; - g0 = _mm_bsrli_si128(g0,8); - g1 = _mm_loadl_epi64((__m128i *)&idxlut[good]); - g1 = _mm_shuffle_epi8(g0,g1); - f1 = _mm256_cvtepi8_epi32(g1); - f2 = _mm256_mulhrs_epi16(f1,v); - f2 = _mm256_mullo_epi16(f2,p); - f1 = _mm256_add_epi32(f1,f2); - _mm256_storeu_si256((__m256i *)&r[ctr],f1); - ctr += _mm_popcnt_u32(good); - pos += 4; - } - - uint32_t t0, t1; - while(ctr < N && pos < REJ_UNIFORM_ETA_BUFLEN) { - t0 = buf[pos] & 0x0F; - t1 = buf[pos++] >> 4; - - if(t0 < 15) { - t0 = t0 - (205*t0 >> 10)*5; - r[ctr++] = 2 - t0; - } - if(t1 < 15 && ctr < N) { - t1 = t1 - (205*t1 >> 10)*5; - r[ctr++] = 2 - t1; - } - } - - return ctr; -} - -#elif ETA == 4 -unsigned int rej_eta_avx(int32_t * restrict r, const uint8_t buf[REJ_UNIFORM_ETA_BUFLEN]) { - unsigned int ctr, pos; - uint32_t good; - __m256i f0, f1; - __m128i g0, g1; - const __m256i mask = _mm256_set1_epi8(15); - const __m256i eta = _mm256_set1_epi8(4); - const __m256i bound = _mm256_set1_epi8(9); - - ctr = pos = 0; - while(ctr <= N - 8 && pos <= REJ_UNIFORM_ETA_BUFLEN - 16) { - f0 = _mm256_cvtepu8_epi16(_mm_loadu_si128((__m128i *)&buf[pos])); - f1 = _mm256_slli_epi16(f0,4); - f0 = _mm256_or_si256(f0,f1); - f0 = _mm256_and_si256(f0,mask); - - f1 = _mm256_sub_epi8(f0,bound); - f0 = _mm256_sub_epi8(eta,f0); - good = _mm256_movemask_epi8(f1); - - g0 = _mm256_castsi256_si128(f0); - g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); - g1 = _mm_shuffle_epi8(g0,g1); - f1 = _mm256_cvtepi8_epi32(g1); - _mm256_storeu_si256((__m256i *)&r[ctr],f1); - ctr += _mm_popcnt_u32(good & 0xFF); - good >>= 8; - pos += 4; - - if(ctr > N - 8) break; - g0 = _mm_bsrli_si128(g0,8); - g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); - g1 = _mm_shuffle_epi8(g0,g1); - f1 = _mm256_cvtepi8_epi32(g1); - _mm256_storeu_si256((__m256i *)&r[ctr],f1); - ctr += _mm_popcnt_u32(good & 0xFF); - good >>= 8; - pos += 4; - - if(ctr > N - 8) break; - g0 = _mm256_extracti128_si256(f0,1); - g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); - g1 = _mm_shuffle_epi8(g0,g1); - f1 = _mm256_cvtepi8_epi32(g1); - _mm256_storeu_si256((__m256i *)&r[ctr],f1); - ctr += _mm_popcnt_u32(good & 0xFF); - good >>= 8; - pos += 4; - - if(ctr > N - 8) break; - g0 = _mm_bsrli_si128(g0,8); - g1 = _mm_loadl_epi64((__m128i *)&idxlut[good]); - g1 = _mm_shuffle_epi8(g0,g1); - f1 = _mm256_cvtepi8_epi32(g1); - _mm256_storeu_si256((__m256i *)&r[ctr],f1); - ctr += _mm_popcnt_u32(good); - pos += 4; - } - - uint32_t t0, t1; - while(ctr < N && pos < REJ_UNIFORM_ETA_BUFLEN) { - t0 = buf[pos] & 0x0F; - t1 = buf[pos++] >> 4; - - if(t0 < 9) - r[ctr++] = 4 - t0; - if(t1 < 9 && ctr < N) - r[ctr++] = 4 - t1; - } - - return ctr; -} -#endif diff --git a/dilithium/avx2/rejsample.h b/dilithium/avx2/rejsample.h deleted file mode 100644 index 61f3f35..0000000 --- a/dilithium/avx2/rejsample.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef REJSAMPLE_H -#define REJSAMPLE_H - -#include -#include "params.h" -#include "symmetric.h" - -#define REJ_UNIFORM_NBLOCKS ((768+STREAM128_BLOCKBYTES-1)/STREAM128_BLOCKBYTES) -#define REJ_UNIFORM_BUFLEN (REJ_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES) - -#if ETA == 2 -#define REJ_UNIFORM_ETA_NBLOCKS ((136+STREAM256_BLOCKBYTES-1)/STREAM256_BLOCKBYTES) -#elif ETA == 4 -#define REJ_UNIFORM_ETA_NBLOCKS ((227+STREAM256_BLOCKBYTES-1)/STREAM256_BLOCKBYTES) -#endif -#define REJ_UNIFORM_ETA_BUFLEN (REJ_UNIFORM_ETA_NBLOCKS*STREAM256_BLOCKBYTES) - -#define idxlut DILITHIUM_NAMESPACE(idxlut) -extern const uint8_t idxlut[256][8]; - -#define rej_uniform_avx DILITHIUM_NAMESPACE(rej_uniform_avx) -unsigned int rej_uniform_avx(int32_t *r, const uint8_t buf[REJ_UNIFORM_BUFLEN+8]); - -#define rej_eta_avx DILITHIUM_NAMESPACE(rej_eta_avx) -unsigned int rej_eta_avx(int32_t *r, const uint8_t buf[REJ_UNIFORM_ETA_BUFLEN]); - -#endif - diff --git a/dilithium/avx2/rounding.c b/dilithium/avx2/rounding.c deleted file mode 100644 index 3ada656..0000000 --- a/dilithium/avx2/rounding.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include "params.h" -#include "rounding.h" -#include "rejsample.h" -#include "consts.h" - -#define _mm256_blendv_epi32(a,b,mask) \ - _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(a), \ - _mm256_castsi256_ps(b), \ - _mm256_castsi256_ps(mask))) - -/************************************************* -* Name: power2round -* -* Description: For finite field elements a, compute a0, a1 such that -* a mod^+ Q = a1*2^D + a0 with -2^{D-1} < a0 <= 2^{D-1}. -* Assumes a to be positive standard representative. -* -* Arguments: - __m256i *a1: output array of length N/8 with high bits -* - __m256i *a0: output array of length N/8 with low bits a0 -* - const __m256i *a: input array of length N/8 -* -**************************************************/ -void power2round_avx(__m256i *a1, __m256i *a0, const __m256i *a) -{ - unsigned int i; - __m256i f,f0,f1; - const __m256i mask = _mm256_set1_epi32(-(1 << D)); - const __m256i half = _mm256_set1_epi32((1 << (D-1)) - 1); - - for(i = 0; i < N/8; ++i) { - f = _mm256_load_si256(&a[i]); - f1 = _mm256_add_epi32(f,half); - f0 = _mm256_and_si256(f1,mask); - f1 = _mm256_srli_epi32(f1,D); - f0 = _mm256_sub_epi32(f,f0); - _mm256_store_si256(&a1[i],f1); - _mm256_store_si256(&a0[i],f0); - } -} - -/************************************************* -* Name: decompose -* -* Description: For finite field element a, compute high and low parts a0, a1 such -* that a mod^+ Q = a1*ALPHA + a0 with -ALPHA/2 < a0 <= ALPHA/2 except -* if a1 = (Q-1)/ALPHA where we set a1 = 0 and -* -ALPHA/2 <= a0 = a mod Q - Q < 0. Assumes a to be positive standard -* representative. -* -* Arguments: - __m256i *a1: output array of length N/8 with high parts -* - __m256i *a0: output array of length N/8 with low parts a0 -* - const __m256i *a: input array of length N/8 -* -**************************************************/ -#if GAMMA2 == (Q-1)/32 -void decompose_avx(__m256i *a1, __m256i *a0, const __m256i *a) -{ - unsigned int i; - __m256i f,f0,f1; - const __m256i q = _mm256_load_si256(&qdata.vec[_8XQ/8]); - const __m256i hq = _mm256_srli_epi32(q,1); - const __m256i v = _mm256_set1_epi32(1025); - const __m256i alpha = _mm256_set1_epi32(2*GAMMA2); - const __m256i off = _mm256_set1_epi32(127); - const __m256i shift = _mm256_set1_epi32(512); - const __m256i mask = _mm256_set1_epi32(15); - - for(i=0;i -#include -#include "params.h" - -#define power2round_avx DILITHIUM_NAMESPACE(power2round_avx) -void power2round_avx(__m256i *a1, __m256i *a0, const __m256i *a); -#define decompose_avx DILITHIUM_NAMESPACE(decompose_avx) -void decompose_avx(__m256i *a1, __m256i *a0, const __m256i *a); -#define make_hint_avx DILITHIUM_NAMESPACE(make_hint_avx) -unsigned int make_hint_avx(uint8_t hint[N], const __m256i *a0, const __m256i *a1); -#define use_hint_avx DILITHIUM_NAMESPACE(use_hint_avx) -void use_hint_avx(__m256i *b, const __m256i *a, const __m256i *hint); - -#endif diff --git a/dilithium/avx2/shuffle.S b/dilithium/avx2/shuffle.S deleted file mode 100644 index 08c757c..0000000 --- a/dilithium/avx2/shuffle.S +++ /dev/null @@ -1,54 +0,0 @@ -#include "consts.h" -.include "shuffle.inc" - -.text -nttunpack128_avx: -#load -vmovdqa (%rdi),%ymm4 -vmovdqa 32(%rdi),%ymm5 -vmovdqa 64(%rdi),%ymm6 -vmovdqa 96(%rdi),%ymm7 -vmovdqa 128(%rdi),%ymm8 -vmovdqa 160(%rdi),%ymm9 -vmovdqa 192(%rdi),%ymm10 -vmovdqa 224(%rdi),%ymm11 - -shuffle8 4,8,3,8 -shuffle8 5,9,4,9 -shuffle8 6,10,5,10 -shuffle8 7,11,6,11 - -shuffle4 3,5,7,5 -shuffle4 8,10,3,10 -shuffle4 4,6,8,6 -shuffle4 9,11,4,11 - -shuffle2 7,8,9,8 -shuffle2 5,6,7,6 -shuffle2 3,4,5,4 -shuffle2 10,11,3,11 - -#store -vmovdqa %ymm9,(%rdi) -vmovdqa %ymm8,32(%rdi) -vmovdqa %ymm7,64(%rdi) -vmovdqa %ymm6,96(%rdi) -vmovdqa %ymm5,128(%rdi) -vmovdqa %ymm4,160(%rdi) -vmovdqa %ymm3,192(%rdi) -vmovdqa %ymm11,224(%rdi) - -ret - -.global cdecl(nttunpack_avx) -cdecl(nttunpack_avx): -call nttunpack128_avx -add $256,%rdi -call nttunpack128_avx -add $256,%rdi -call nttunpack128_avx -add $256,%rdi -call nttunpack128_avx -ret - -.section .note.GNU-stack,"",@progbits diff --git a/dilithium/avx2/shuffle.inc b/dilithium/avx2/shuffle.inc deleted file mode 100644 index 73e9ffe..0000000 --- a/dilithium/avx2/shuffle.inc +++ /dev/null @@ -1,25 +0,0 @@ -.macro shuffle8 r0,r1,r2,r3 -vperm2i128 $0x20,%ymm\r1,%ymm\r0,%ymm\r2 -vperm2i128 $0x31,%ymm\r1,%ymm\r0,%ymm\r3 -.endm - -.macro shuffle4 r0,r1,r2,r3 -vpunpcklqdq %ymm\r1,%ymm\r0,%ymm\r2 -vpunpckhqdq %ymm\r1,%ymm\r0,%ymm\r3 -.endm - -.macro shuffle2 r0,r1,r2,r3 -#vpsllq $32,%ymm\r1,%ymm\r2 -vmovsldup %ymm\r1,%ymm\r2 -vpblendd $0xAA,%ymm\r2,%ymm\r0,%ymm\r2 -vpsrlq $32,%ymm\r0,%ymm\r0 -#vmovshdup %ymm\r0,%ymm\r0 -vpblendd $0xAA,%ymm\r1,%ymm\r0,%ymm\r3 -.endm - -.macro shuffle1 r0,r1,r2,r3 -vpslld $16,%ymm\r1,%ymm\r2 -vpblendw $0xAA,%ymm\r2,%ymm\r0,%ymm\r2 -vpsrld $16,%ymm\r0,%ymm\r0 -vpblendw $0xAA,%ymm\r1,%ymm\r0,%ymm\r3 -.endm diff --git a/dilithium/avx2/sign.c b/dilithium/avx2/sign.c deleted file mode 100644 index efb6ea3..0000000 --- a/dilithium/avx2/sign.c +++ /dev/null @@ -1,530 +0,0 @@ -#include -#include -#include "align.h" -#include "params.h" -#include "sign.h" -#include "packing.h" -#include "polyvec.h" -#include "poly.h" -#include "randombytes.h" -#include "symmetric.h" -#include "fips202.h" - -static inline void polyvec_matrix_expand_row(polyvecl **row, polyvecl buf[2], const uint8_t rho[SEEDBYTES], unsigned int i) { - switch(i) { - case 0: - polyvec_matrix_expand_row0(buf, buf + 1, rho); - *row = buf; - break; - case 1: - polyvec_matrix_expand_row1(buf + 1, buf, rho); - *row = buf + 1; - break; - case 2: - polyvec_matrix_expand_row2(buf, buf + 1, rho); - *row = buf; - break; - case 3: - polyvec_matrix_expand_row3(buf + 1, buf, rho); - *row = buf + 1; - break; -#if K > 4 - case 4: - polyvec_matrix_expand_row4(buf, buf + 1, rho); - *row = buf; - break; - case 5: - polyvec_matrix_expand_row5(buf + 1, buf, rho); - *row = buf + 1; - break; -#endif -#if K > 6 - case 6: - polyvec_matrix_expand_row6(buf, buf + 1, rho); - *row = buf; - break; - case 7: - polyvec_matrix_expand_row7(buf + 1, buf, rho); - *row = buf + 1; - break; -#endif - } -} - -/************************************************* -* Name: crypto_sign_keypair -* -* Description: Generates public and private key. -* -* Arguments: - uint8_t *pk: pointer to output public key (allocated -* array of CRYPTO_PUBLICKEYBYTES bytes) -* - uint8_t *sk: pointer to output private key (allocated -* array of CRYPTO_SECRETKEYBYTES bytes) -* -* Returns 0 (success) -**************************************************/ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - unsigned int i; - uint8_t seedbuf[2*SEEDBYTES + CRHBYTES]; - const uint8_t *rho, *rhoprime, *key; - polyvecl rowbuf[2]; - polyvecl s1, *row = rowbuf; - polyveck s2; - poly t1, t0; - - /* Get randomness for rho, rhoprime and key */ - randombytes(seedbuf, SEEDBYTES); - seedbuf[SEEDBYTES+0] = K; - seedbuf[SEEDBYTES+1] = L; - shake256(seedbuf, 2*SEEDBYTES + CRHBYTES, seedbuf, SEEDBYTES+2); - rho = seedbuf; - rhoprime = rho + SEEDBYTES; - key = rhoprime + CRHBYTES; - - /* Store rho, key */ - memcpy(pk, rho, SEEDBYTES); - memcpy(sk, rho, SEEDBYTES); - memcpy(sk + SEEDBYTES, key, SEEDBYTES); - - /* Sample short vectors s1 and s2 */ -#if K == 4 && L == 4 - poly_uniform_eta_4x(&s1.vec[0], &s1.vec[1], &s1.vec[2], &s1.vec[3], rhoprime, 0, 1, 2, 3); - poly_uniform_eta_4x(&s2.vec[0], &s2.vec[1], &s2.vec[2], &s2.vec[3], rhoprime, 4, 5, 6, 7); -#elif K == 6 && L == 5 - poly_uniform_eta_4x(&s1.vec[0], &s1.vec[1], &s1.vec[2], &s1.vec[3], rhoprime, 0, 1, 2, 3); - poly_uniform_eta_4x(&s1.vec[4], &s2.vec[0], &s2.vec[1], &s2.vec[2], rhoprime, 4, 5, 6, 7); - poly_uniform_eta_4x(&s2.vec[3], &s2.vec[4], &s2.vec[5], &t0, rhoprime, 8, 9, 10, 11); -#elif K == 8 && L == 7 - poly_uniform_eta_4x(&s1.vec[0], &s1.vec[1], &s1.vec[2], &s1.vec[3], rhoprime, 0, 1, 2, 3); - poly_uniform_eta_4x(&s1.vec[4], &s1.vec[5], &s1.vec[6], &s2.vec[0], rhoprime, 4, 5, 6, 7); - poly_uniform_eta_4x(&s2.vec[1], &s2.vec[2], &s2.vec[3], &s2.vec[4], rhoprime, 8, 9, 10, 11); - poly_uniform_eta_4x(&s2.vec[5], &s2.vec[6], &s2.vec[7], &t0, rhoprime, 12, 13, 14, 15); -#else -#error -#endif - - /* Pack secret vectors */ - for(i = 0; i < L; i++) - polyeta_pack(sk + 2*SEEDBYTES + TRBYTES + i*POLYETA_PACKEDBYTES, &s1.vec[i]); - for(i = 0; i < K; i++) - polyeta_pack(sk + 2*SEEDBYTES + TRBYTES + (L + i)*POLYETA_PACKEDBYTES, &s2.vec[i]); - - /* Transform s1 */ - polyvecl_ntt(&s1); - - for(i = 0; i < K; i++) { - /* Expand matrix row */ - polyvec_matrix_expand_row(&row, rowbuf, rho, i); - - /* Compute inner-product */ - polyvecl_pointwise_acc_montgomery(&t1, row, &s1); - poly_invntt_tomont(&t1); - - /* Add error polynomial */ - poly_add(&t1, &t1, &s2.vec[i]); - - /* Round t and pack t1, t0 */ - poly_caddq(&t1); - poly_power2round(&t1, &t0, &t1); - polyt1_pack(pk + SEEDBYTES + i*POLYT1_PACKEDBYTES, &t1); - polyt0_pack(sk + 2*SEEDBYTES + TRBYTES + (L+K)*POLYETA_PACKEDBYTES + i*POLYT0_PACKEDBYTES, &t0); - } - - /* Compute H(rho, t1) and store in secret key */ - shake256(sk + 2*SEEDBYTES, TRBYTES, pk, CRYPTO_PUBLICKEYBYTES); - - return 0; -} - -/************************************************* -* Name: crypto_sign_signature_internal -* -* Description: Computes signature. Internal API. -* -* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES) -* - size_t *siglen: pointer to output length of signature -* - uint8_t *m: pointer to message to be signed -* - size_t mlen: length of message -* - uint8_t *pre: pointer to prefix string -* - size_t prelen: length of prefix string -* - uint8_t *rnd: pointer to random seed -* - uint8_t *sk: pointer to bit-packed secret key -* -* Returns 0 (success) -**************************************************/ -int crypto_sign_signature_internal(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, - const uint8_t *pre, size_t prelen, const uint8_t rnd[RNDBYTES], const uint8_t *sk) -{ - unsigned int i, n, pos; - uint8_t seedbuf[2*SEEDBYTES + TRBYTES + 2*CRHBYTES]; - uint8_t *rho, *tr, *key, *mu, *rhoprime; - uint8_t hintbuf[N]; - uint8_t *hint = sig + CTILDEBYTES + L*POLYZ_PACKEDBYTES; - uint64_t nonce = 0; - polyvecl mat[K], s1, z; - polyveck t0, s2, w1; - poly c, tmp; - union { - polyvecl y; - polyveck w0; - } tmpv; - keccak_state state; - - rho = seedbuf; - tr = rho + SEEDBYTES; - key = tr + TRBYTES; - mu = key + SEEDBYTES; - rhoprime = mu + CRHBYTES; - unpack_sk(rho, tr, key, &t0, &s1, &s2, sk); - - /* Compute mu = CRH(tr, pre, msg) */ - shake256_init(&state); - shake256_absorb(&state, tr, TRBYTES); - shake256_absorb(&state, pre, prelen); - shake256_absorb(&state, m, mlen); - shake256_finalize(&state); - shake256_squeeze(mu, CRHBYTES, &state); - - /* Compute rhoprime = CRH(key, rnd, mu) */ - shake256_init(&state); - shake256_absorb(&state, key, SEEDBYTES); - shake256_absorb(&state, rnd, RNDBYTES); - shake256_absorb(&state, mu, CRHBYTES); - shake256_finalize(&state); - shake256_squeeze(rhoprime, CRHBYTES, &state); - - /* Expand matrix and transform vectors */ - polyvec_matrix_expand(mat, rho); - polyvecl_ntt(&s1); - polyveck_ntt(&s2); - polyveck_ntt(&t0); - -rej: - /* Sample intermediate vector y */ -#if L == 4 - poly_uniform_gamma1_4x(&z.vec[0], &z.vec[1], &z.vec[2], &z.vec[3], - rhoprime, nonce, nonce + 1, nonce + 2, nonce + 3); - nonce += 4; -#elif L == 5 - poly_uniform_gamma1_4x(&z.vec[0], &z.vec[1], &z.vec[2], &z.vec[3], - rhoprime, nonce, nonce + 1, nonce + 2, nonce + 3); - poly_uniform_gamma1(&z.vec[4], rhoprime, nonce + 4); - nonce += 5; -#elif L == 7 - poly_uniform_gamma1_4x(&z.vec[0], &z.vec[1], &z.vec[2], &z.vec[3], - rhoprime, nonce, nonce + 1, nonce + 2, nonce + 3); - poly_uniform_gamma1_4x(&z.vec[4], &z.vec[5], &z.vec[6], &tmp, - rhoprime, nonce + 4, nonce + 5, nonce + 6, 0); - nonce += 7; -#else -#error -#endif - - /* Matrix-vector product */ - tmpv.y = z; - polyvecl_ntt(&tmpv.y); - polyvec_matrix_pointwise_montgomery(&w1, mat, &tmpv.y); - polyveck_invntt_tomont(&w1); - - /* Decompose w and call the random oracle */ - polyveck_caddq(&w1); - polyveck_decompose(&w1, &tmpv.w0, &w1); - polyveck_pack_w1(sig, &w1); - - shake256_init(&state); - shake256_absorb(&state, mu, CRHBYTES); - shake256_absorb(&state, sig, K*POLYW1_PACKEDBYTES); - shake256_finalize(&state); - shake256_squeeze(sig, CTILDEBYTES, &state); - poly_challenge(&c, sig); - poly_ntt(&c); - - /* Compute z, reject if it reveals secret */ - for(i = 0; i < L; i++) { - poly_pointwise_montgomery(&tmp, &c, &s1.vec[i]); - poly_invntt_tomont(&tmp); - poly_add(&z.vec[i], &z.vec[i], &tmp); - poly_reduce(&z.vec[i]); - if(poly_chknorm(&z.vec[i], GAMMA1 - BETA)) - goto rej; - } - - /* Zero hint vector in signature */ - pos = 0; - memset(hint, 0, OMEGA); - - for(i = 0; i < K; i++) { - /* Check that subtracting cs2 does not change high bits of w and low bits - * do not reveal secret information */ - poly_pointwise_montgomery(&tmp, &c, &s2.vec[i]); - poly_invntt_tomont(&tmp); - poly_sub(&tmpv.w0.vec[i], &tmpv.w0.vec[i], &tmp); - poly_reduce(&tmpv.w0.vec[i]); - if(poly_chknorm(&tmpv.w0.vec[i], GAMMA2 - BETA)) - goto rej; - - /* Compute hints */ - poly_pointwise_montgomery(&tmp, &c, &t0.vec[i]); - poly_invntt_tomont(&tmp); - poly_reduce(&tmp); - if(poly_chknorm(&tmp, GAMMA2)) - goto rej; - - poly_add(&tmpv.w0.vec[i], &tmpv.w0.vec[i], &tmp); - n = poly_make_hint(hintbuf, &tmpv.w0.vec[i], &w1.vec[i]); - if(pos + n > OMEGA) - goto rej; - - /* Store hints in signature */ - memcpy(&hint[pos], hintbuf, n); - hint[OMEGA + i] = pos = pos + n; - } - - /* Pack z into signature */ - for(i = 0; i < L; i++) - polyz_pack(sig + CTILDEBYTES + i*POLYZ_PACKEDBYTES, &z.vec[i]); - - *siglen = CRYPTO_BYTES; - return 0; -} - -/************************************************* -* Name: crypto_sign_signature -* -* Description: Computes signature. -* -* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES) -* - size_t *siglen: pointer to output length of signature -* - uint8_t *m: pointer to message to be signed -* - size_t mlen: length of message -* - uint8_t *ctx: pointer to context string -* - size_t ctxlen: length of context string -* - uint8_t *sk: pointer to bit-packed secret key -* -* Returns 0 (success) or -1 (context string too long) -**************************************************/ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, const uint8_t *sk) -{ - uint8_t pre[257]; - uint8_t rnd[RNDBYTES]; - - if(ctxlen > 255) - return -1; - - /* Prepare pre = (0, ctxlen, ctx) */ - pre[0] = 0; - pre[1] = ctxlen; - memcpy(&pre[2], ctx, ctxlen); - -#ifdef DILITHIUM_RANDOMIZED_SIGNING - randombytes(rnd, RNDBYTES); -#else - memset(rnd, 0, RNDBYTES); -#endif - - crypto_sign_signature_internal(sig,siglen,m,mlen,pre,2+ctxlen,rnd,sk); - return 0; -} - -/************************************************* -* Name: crypto_sign -* -* Description: Compute signed message. -* -* Arguments: - uint8_t *sm: pointer to output signed message (allocated -* array with CRYPTO_BYTES + mlen bytes), -* can be equal to m -* - size_t *smlen: pointer to output length of signed -* message -* - const uint8_t *m: pointer to message to be signed -* - size_t mlen: length of message -* - const uint8_t *ctx: pointer to context string -* - size_t ctxlen: length of context string -* - const uint8_t *sk: pointer to bit-packed secret key -* -* Returns 0 (success) -**************************************************/ -int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk) -{ - size_t i; - int ret; - - for(i = 0; i < mlen; ++i) - sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - ret = crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, ctx, ctxlen, sk); - *smlen += mlen; - return ret; -} - -/************************************************* -* Name: crypto_sign_verify_internal -* -* Description: Verifies signature. Internal API. -* -* Arguments: - uint8_t *m: pointer to input signature -* - size_t siglen: length of signature -* - const uint8_t *m: pointer to message -* - size_t mlen: length of message -* - const uint8_t *pre: pointer to prefix string -* - size_t prelen: length of prefix string -* - const uint8_t *pk: pointer to bit-packed public key -* -* Returns 0 if signature could be verified correctly and -1 otherwise -**************************************************/ -int crypto_sign_verify_internal(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, - const uint8_t *pre, size_t prelen, const uint8_t *pk) { - unsigned int i, j, pos = 0; - /* polyw1_pack writes additional 14 bytes */ - ALIGNED_UINT8(K*POLYW1_PACKEDBYTES+14) buf; - uint8_t mu[CRHBYTES]; - const uint8_t *hint = sig + CTILDEBYTES + L*POLYZ_PACKEDBYTES; - polyvecl rowbuf[2]; - polyvecl *row = rowbuf; - polyvecl z; - poly c, w1, h; - keccak_state state; - - if(siglen != CRYPTO_BYTES) - return -1; - - /* Compute CRH(H(rho, t1), pre, msg) */ - shake256(mu, TRBYTES, pk, CRYPTO_PUBLICKEYBYTES); - shake256_init(&state); - shake256_absorb(&state, mu, CRHBYTES); - shake256_absorb(&state, pre, prelen); - shake256_absorb(&state, m, mlen); - shake256_finalize(&state); - shake256_squeeze(mu, CRHBYTES, &state); - - /* Expand challenge */ - poly_challenge(&c, sig); - poly_ntt(&c); - - /* Unpack z; shortness follows from unpacking */ - for(i = 0; i < L; i++) { - polyz_unpack(&z.vec[i], sig + CTILDEBYTES + i*POLYZ_PACKEDBYTES); - poly_ntt(&z.vec[i]); - } - - for(i = 0; i < K; i++) { - /* Expand matrix row */ - polyvec_matrix_expand_row(&row, rowbuf, pk, i); - - /* Compute i-th row of Az - c2^Dt1 */ - polyvecl_pointwise_acc_montgomery(&w1, row, &z); - - polyt1_unpack(&h, pk + SEEDBYTES + i*POLYT1_PACKEDBYTES); - poly_shiftl(&h); - poly_ntt(&h); - poly_pointwise_montgomery(&h, &c, &h); - - poly_sub(&w1, &w1, &h); - poly_reduce(&w1); - poly_invntt_tomont(&w1); - - /* Get hint polynomial and reconstruct w1 */ - memset(h.vec, 0, sizeof(poly)); - if(hint[OMEGA + i] < pos || hint[OMEGA + i] > OMEGA) - return -1; - - for(j = pos; j < hint[OMEGA + i]; ++j) { - /* Coefficients are ordered for strong unforgeability */ - if(j > pos && hint[j] <= hint[j-1]) return -1; - h.coeffs[hint[j]] = 1; - } - pos = hint[OMEGA + i]; - - poly_caddq(&w1); - poly_use_hint(&w1, &w1, &h); - polyw1_pack(buf.coeffs + i*POLYW1_PACKEDBYTES, &w1); - } - - /* Extra indices are zero for strong unforgeability */ - for(j = pos; j < OMEGA; ++j) - if(hint[j]) return -1; - - /* Call random oracle and verify challenge */ - shake256_init(&state); - shake256_absorb(&state, mu, CRHBYTES); - shake256_absorb(&state, buf.coeffs, K*POLYW1_PACKEDBYTES); - shake256_finalize(&state); - shake256_squeeze(buf.coeffs, CTILDEBYTES, &state); - for(i = 0; i < CTILDEBYTES; ++i) - if(buf.coeffs[i] != sig[i]) - return -1; - - return 0; -} - -/************************************************* -* Name: crypto_sign_verify -* -* Description: Verifies signature. -* -* Arguments: - uint8_t *m: pointer to input signature -* - size_t siglen: length of signature -* - const uint8_t *m: pointer to message -* - size_t mlen: length of message -* - const uint8_t *ctx: pointer to context string -* - size_t ctxlen: length of context string -* - const uint8_t *pk: pointer to bit-packed public key -* -* Returns 0 if signature could be verified correctly and -1 otherwise -**************************************************/ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, const uint8_t *pk) -{ - uint8_t pre[257]; - - if(ctxlen > 255) - return -1; - - pre[0] = 0; - pre[1] = ctxlen; - memcpy(&pre[2], ctx, ctxlen); - return crypto_sign_verify_internal(sig,siglen,m,mlen,pre,2+ctxlen,pk); -} - -/************************************************* -* Name: crypto_sign_open -* -* Description: Verify signed message. -* -* Arguments: - uint8_t *m: pointer to output message (allocated -* array with smlen bytes), can be equal to sm -* - size_t *mlen: pointer to output length of message -* - const uint8_t *sm: pointer to signed message -* - size_t smlen: length of signed message -* - const uint8_t *ctx: pointer to context string -* - size_t ctxlen: length of context string -* - const uint8_t *pk: pointer to bit-packed public key -* -* Returns 0 if signed message could be verified correctly and -1 otherwise -**************************************************/ -int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, - const uint8_t *ctx, size_t ctxlen, const uint8_t *pk) { - size_t i; - - if(smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - if(crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, ctx, ctxlen, pk)) - goto badsig; - else { - /* All good, copy msg, return 0 */ - for(i = 0; i < *mlen; ++i) - m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = 0; - for(i = 0; i < smlen; ++i) - m[i] = 0; - - return -1; -} diff --git a/dilithium/avx2/sign.h b/dilithium/avx2/sign.h deleted file mode 120000 index 200b72f..0000000 --- a/dilithium/avx2/sign.h +++ /dev/null @@ -1 +0,0 @@ -../ref/sign.h \ No newline at end of file diff --git a/dilithium/avx2/symmetric-shake.c b/dilithium/avx2/symmetric-shake.c deleted file mode 120000 index 86f8b6c..0000000 --- a/dilithium/avx2/symmetric-shake.c +++ /dev/null @@ -1 +0,0 @@ -../ref/symmetric-shake.c \ No newline at end of file diff --git a/dilithium/avx2/symmetric.h b/dilithium/avx2/symmetric.h deleted file mode 100644 index 8f3c3c5..0000000 --- a/dilithium/avx2/symmetric.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SYMMETRIC_H -#define SYMMETRIC_H - -#include -#include "params.h" - -#include "fips202.h" - -typedef keccak_state stream128_state; -typedef keccak_state stream256_state; - -#define dilithium_shake128_stream_init DILITHIUM_NAMESPACE(dilithium_shake128_stream_init) -void dilithium_shake128_stream_init(keccak_state *state, const uint8_t seed[SEEDBYTES], uint16_t nonce); - -#define dilithium_shake256_stream_init DILITHIUM_NAMESPACE(dilithium_shake256_stream_init) -void dilithium_shake256_stream_init(keccak_state *state, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define STREAM128_BLOCKBYTES SHAKE128_RATE -#define STREAM256_BLOCKBYTES SHAKE256_RATE - -#define stream128_init(STATE, SEED, NONCE) dilithium_shake128_stream_init(STATE, SEED, NONCE) -#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) shake128_squeezeblocks(OUT, OUTBLOCKS, STATE) -#define stream256_init(STATE, SEED, NONCE) dilithium_shake256_stream_init(STATE, SEED, NONCE) -#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) - -#endif diff --git a/dilithium/avx2/test/.gitignore b/dilithium/avx2/test/.gitignore deleted file mode 100644 index 99b3f73..0000000 --- a/dilithium/avx2/test/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -test_dilithium2 -test_dilithium3 -test_dilithium5 -test_vectors2 -test_vectors3 -test_vectors5 -test_speed2 -test_speed3 -test_speed5 -test_mul diff --git a/dilithium/avx2/test/cpucycles.c b/dilithium/avx2/test/cpucycles.c deleted file mode 120000 index 4d6fc8a..0000000 --- a/dilithium/avx2/test/cpucycles.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/cpucycles.c \ No newline at end of file diff --git a/dilithium/avx2/test/cpucycles.h b/dilithium/avx2/test/cpucycles.h deleted file mode 120000 index 269feb3..0000000 --- a/dilithium/avx2/test/cpucycles.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/cpucycles.h \ No newline at end of file diff --git a/dilithium/avx2/test/speed_print.c b/dilithium/avx2/test/speed_print.c deleted file mode 120000 index 98f2a46..0000000 --- a/dilithium/avx2/test/speed_print.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/speed_print.c \ No newline at end of file diff --git a/dilithium/avx2/test/speed_print.h b/dilithium/avx2/test/speed_print.h deleted file mode 120000 index 8ba4e5e..0000000 --- a/dilithium/avx2/test/speed_print.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/speed_print.h \ No newline at end of file diff --git a/dilithium/avx2/test/test_dilithium.c b/dilithium/avx2/test/test_dilithium.c deleted file mode 120000 index 729cb5b..0000000 --- a/dilithium/avx2/test/test_dilithium.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/test_dilithium.c \ No newline at end of file diff --git a/dilithium/avx2/test/test_mul.c b/dilithium/avx2/test/test_mul.c deleted file mode 120000 index 013f7af..0000000 --- a/dilithium/avx2/test/test_mul.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/test_mul.c \ No newline at end of file diff --git a/dilithium/avx2/test/test_speed.c b/dilithium/avx2/test/test_speed.c deleted file mode 120000 index 7decc02..0000000 --- a/dilithium/avx2/test/test_speed.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/test_speed.c \ No newline at end of file diff --git a/dilithium/avx2/test/test_vectors.c b/dilithium/avx2/test/test_vectors.c deleted file mode 100644 index 430ff2a..0000000 --- a/dilithium/avx2/test/test_vectors.c +++ /dev/null @@ -1,275 +0,0 @@ -#include -#include -#include -#include -#include "../randombytes.h" -#include "../fips202.h" -#include "../params.h" -#include "../sign.h" -#include "../poly.h" -#include "../polyvec.h" -#include "../packing.h" - -#define MLEN 32 -#define CTXLEN 13 -#define NVECTORS 10000 - -static unsigned int nttidx(unsigned int k) { - unsigned int r; - r = k/64*64; - k %= 64; - r += k/8; - k %= 8; - r += k*8; - return r; -} - -/* Initital state after absorbing empty string - * Permute before squeeze is achieved by setting pos to SHAKE128_RATE */ -static keccak_state rngstate = {{0x1F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (1ULL << 63), 0, 0, 0, 0}, SHAKE128_RATE}; - -void randombytes(uint8_t *x,size_t xlen) { - shake128_squeeze(x, xlen, &rngstate); -} - -int main(void) { - unsigned int i, j, k, l; - uint8_t pk[CRYPTO_PUBLICKEYBYTES]; - uint8_t sk[CRYPTO_SECRETKEYBYTES]; - uint8_t sig[CRYPTO_BYTES]; - uint8_t m[MLEN]; - uint8_t ctx[CTXLEN] = {0}; - uint8_t seed[CRHBYTES]; - uint8_t buf[CRYPTO_SECRETKEYBYTES]; - size_t siglen; - poly c, tmp; - polyvecl s, y, mat[K]; - polyveck w, w1, w0, t1, t0; - - snprintf((char*)ctx,CTXLEN,"test_vectors"); - - for(i = 0; i < NVECTORS; ++i) { - printf("count = %u\n", i); - - randombytes(m, MLEN); - printf("m = "); - for(j = 0; j < MLEN; ++j) - printf("%02x", m[j]); - printf("\n"); - - crypto_sign_keypair(pk, sk); - shake256(buf, 32, pk, CRYPTO_PUBLICKEYBYTES); - printf("pk = "); - for(j = 0; j < 32; ++j) - printf("%02x", buf[j]); - printf("\n"); - shake256(buf, 32, sk, CRYPTO_SECRETKEYBYTES); - printf("sk = "); - for(j = 0; j < 32; ++j) - printf("%02x", buf[j]); - printf("\n"); - - crypto_sign_signature(sig, &siglen, m, MLEN, ctx, CTXLEN, sk); - shake256(buf, 32, sig, CRYPTO_BYTES); - printf("sig = "); - for(j = 0; j < 32; ++j) - printf("%02x", buf[j]); - printf("\n"); - - if(crypto_sign_verify(sig, siglen, m, MLEN, ctx, CTXLEN, pk)) - fprintf(stderr,"Signature verification failed!\n"); - - randombytes(seed, sizeof(seed)); - printf("seed = "); - for(j = 0; j < sizeof(seed); ++j) - printf("%02X", seed[j]); - printf("\n"); - - polyvec_matrix_expand(mat, seed); - printf("A = (["); - for(j = 0; j < K; ++j) { - for(k = 0; k < L; ++k) { - for(l = 0; l < N; ++l) { - printf("%8d", mat[j].vec[k].coeffs[nttidx(l)]); - if(l < N-1) printf(", "); - else if(k < L-1) printf("], ["); - else if(j < K-1) printf("];\n ["); - else printf("])\n"); - } - } - } - - -#if L == 4 - poly_uniform_eta_4x(&s.vec[0], &s.vec[1], &s.vec[2], &s.vec[3], seed, 0, 1, 2, 3); -#elif L == 5 - poly_uniform_eta_4x(&s.vec[0], &s.vec[1], &s.vec[2], &s.vec[3], seed, 0, 1, 2, 3); - poly_uniform_eta(&s.vec[4], seed, 4); -#elif L == 7 - poly_uniform_eta_4x(&s.vec[0], &s.vec[1], &s.vec[2], &s.vec[3], seed, 0, 1, 2, 3); - poly_uniform_eta_4x(&s.vec[4], &s.vec[5], &s.vec[6], &tmp, seed, 4, 5, 6, 7); -#else -#error -#endif - - polyeta_pack(buf, &s.vec[0]); - polyeta_unpack(&tmp, buf); - for(j = 0; j < N; ++j) - if(tmp.coeffs[j] != s.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in polyeta_(un)pack!\n"); - - if(polyvecl_chknorm(&s, ETA+1)) - fprintf(stderr, "ERROR in polyvecl_chknorm(&s ,ETA+1)!\n"); - - printf("s = (["); - for(j = 0; j < L; ++j) { - for(k = 0; k < N; ++k) { - printf("%3d", s.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < L-1) printf("],\n ["); - else printf("])\n"); - } - } - -#if L == 4 - poly_uniform_gamma1_4x(&y.vec[0], &y.vec[1], &y.vec[2], &y.vec[3], seed, 0, 1, 2, 3); -#elif L == 5 - poly_uniform_gamma1_4x(&y.vec[0], &y.vec[1], &y.vec[2], &y.vec[3], seed, 0, 1, 2, 3); - poly_uniform_gamma1(&y.vec[4], seed, 4); -#elif L == 7 - poly_uniform_gamma1_4x(&y.vec[0], &y.vec[1], &y.vec[2], &y.vec[3], seed, 0, 1, 2, 3); - poly_uniform_gamma1_4x(&y.vec[4], &y.vec[5], &y.vec[6], &tmp, seed, 4, 5, 6, 7); -#else -#error -#endif - - polyz_pack(buf, &y.vec[0]); - polyz_unpack(&tmp, buf); - for(j = 0; j < N; ++j) - if(tmp.coeffs[j] != y.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in polyz_(un)pack!\n"); - - if(polyvecl_chknorm(&y, GAMMA1+1)) - fprintf(stderr, "ERROR in polyvecl_chknorm(&y, GAMMA1)!\n"); - - printf("y = (["); - for(j = 0; j < L; ++j) { - for(k = 0; k < N; ++k) { - printf("%8d", y.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < L-1) printf("],\n ["); - else printf("])\n"); - } - } - - polyvecl_ntt(&y); - polyvec_matrix_pointwise_montgomery(&w, mat, &y); - polyveck_invntt_tomont(&w); - polyveck_caddq(&w); - polyveck_decompose(&w1, &w0, &w); - - for(j = 0; j < N; ++j) { - tmp.coeffs[j] = w1.vec[0].coeffs[j]*2*GAMMA2 + w0.vec[0].coeffs[j]; - if(tmp.coeffs[j] < 0) tmp.coeffs[j] += Q; - if(tmp.coeffs[j] != w.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in poly_decompose!\n"); - } - - polyw1_pack(buf, &w1.vec[0]); -#if GAMMA2 == (Q-1)/32 - for(j = 0; j < N/2; ++j) { - tmp.coeffs[2*j+0] = buf[j] & 0xF; - tmp.coeffs[2*j+1] = buf[j] >> 4; - if(tmp.coeffs[2*j+0] != w1.vec[0].coeffs[2*j+0] - || tmp.coeffs[2*j+1] != w1.vec[0].coeffs[2*j+1]) - fprintf(stderr, "ERROR in polyw1_pack!\n"); - } -#endif - -#if GAMMA2 == (Q-1)/32 - if(polyveck_chknorm(&w1, 16)) - fprintf(stderr, "ERROR in polyveck_chknorm(&w1, 16)!\n"); -#elif GAMMA2 == (Q-1)/88 - if(polyveck_chknorm(&w1, 44)) - fprintf(stderr, "ERROR in polyveck_chknorm(&w1, 44)!\n"); -#endif - if(polyveck_chknorm(&w0, GAMMA2 + 1)) - fprintf(stderr, "ERROR in polyveck_chknorm(&w0, GAMMA2+1)!\n"); - - printf("w1 = (["); - for(j = 0; j < K; ++j) { - for(k = 0; k < N; ++k) { - printf("%2d", w1.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < K-1) printf("],\n ["); - else printf("])\n"); - } - } - printf("w0 = (["); - for(j = 0; j < K; ++j) { - for(k = 0; k < N; ++k) { - printf("%8d", w0.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < K-1) printf("],\n ["); - else printf("])\n"); - } - } - - polyveck_power2round(&t1, &t0, &w); - - for(j = 0; j < N; ++j) { - tmp.coeffs[j] = (t1.vec[0].coeffs[j] << D) + t0.vec[0].coeffs[j]; - if(tmp.coeffs[j] != w.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in poly_power2round!\n"); - } - - polyt1_pack(buf, &t1.vec[0]); - polyt1_unpack(&tmp, buf); - for(j = 0; j < N; ++j) { - if(tmp.coeffs[j] != t1.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in polyt1_(un)pack!\n"); - } - polyt0_pack(buf, &t0.vec[0]); - polyt0_unpack(&tmp, buf); - for(j = 0; j < N; ++j) { - if(tmp.coeffs[j] != t0.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in polyt0_(un)pack!\n"); - } - - if(polyveck_chknorm(&t1, 1024)) - fprintf(stderr, "ERROR in polyveck_chknorm(&t1, 1024)!\n"); - if(polyveck_chknorm(&t0, (1U << (D-1)) + 1)) - fprintf(stderr, "ERROR in polyveck_chknorm(&t0, (1 << (D-1)) + 1)!\n"); - - printf("t1 = (["); - for(j = 0; j < K; ++j) { - for(k = 0; k < N; ++k) { - printf("%3d", t1.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < K-1) printf("],\n ["); - else printf("])\n"); - } - } - printf("t0 = (["); - for(j = 0; j < K; ++j) { - for(k = 0; k < N; ++k) { - printf("%5d", t0.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < K-1) printf("],\n ["); - else printf("])\n"); - } - } - - poly_challenge(&c, seed); - printf("c = ["); - for(j = 0; j < N; ++j) { - printf("%2d", c.coeffs[j]); - if(j < N-1) printf(", "); - else printf("]\n"); - } - - printf("\n"); - } - - return 0; -} diff --git a/dilithium/ref/.gitignore b/dilithium/ref/.gitignore deleted file mode 100644 index cc78368..0000000 --- a/dilithium/ref/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.so -*.o diff --git a/dilithium/ref/Makefile b/dilithium/ref/Makefile deleted file mode 100644 index 2c94d35..0000000 --- a/dilithium/ref/Makefile +++ /dev/null @@ -1,139 +0,0 @@ -CC ?= /usr/bin/cc -CFLAGS += -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wredundant-decls \ - -Wshadow -Wvla -Wpointer-arith -O3 -fomit-frame-pointer -NISTFLAGS += -Wno-unused-result -O3 -fomit-frame-pointer -SOURCES = sign.c packing.c polyvec.c poly.c ntt.c reduce.c rounding.c -HEADERS = config.h params.h api.h sign.h packing.h polyvec.h poly.h ntt.h \ - reduce.h rounding.h symmetric.h randombytes.h -KECCAK_SOURCES = $(SOURCES) fips202.c symmetric-shake.c -KECCAK_HEADERS = $(HEADERS) fips202.h - -.PHONY: all speed shared clean - -all: \ - test/test_dilithium2 \ - test/test_dilithium3 \ - test/test_dilithium5 \ - test/test_vectors2 \ - test/test_vectors3 \ - test/test_vectors5 - -nistkat: \ - nistkat/PQCgenKAT_sign2 \ - nistkat/PQCgenKAT_sign3 \ - nistkat/PQCgenKAT_sign5 - -speed: \ - test/test_mul \ - test/test_speed2 \ - test/test_speed3 \ - test/test_speed5 \ - -shared: \ - libpqcrystals_dilithium2_ref.so \ - libpqcrystals_dilithium3_ref.so \ - libpqcrystals_dilithium5_ref.so \ - libpqcrystals_fips202_ref.so \ - -libpqcrystals_fips202_ref.so: fips202.c fips202.h - $(CC) -shared -fPIC $(CFLAGS) -o $@ $< - -libpqcrystals_dilithium2_ref.so: $(SOURCES) $(HEADERS) symmetric-shake.c - $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=2 \ - -o $@ $(SOURCES) symmetric-shake.c - -libpqcrystals_dilithium3_ref.so: $(SOURCES) $(HEADERS) symmetric-shake.c - $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=3 \ - -o $@ $(SOURCES) symmetric-shake.c - -libpqcrystals_dilithium5_ref.so: $(SOURCES) $(HEADERS) symmetric-shake.c - $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=5 \ - -o $@ $(SOURCES) symmetric-shake.c - -test/test_dilithium2: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ - -o $@ $< randombytes.c $(KECCAK_SOURCES) - -test/test_dilithium3: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ - -o $@ $< randombytes.c $(KECCAK_SOURCES) - -test/test_dilithium5: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ - -o $@ $< randombytes.c $(KECCAK_SOURCES) - -test/test_vectors2: test/test_vectors.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ - -o $@ $< $(KECCAK_SOURCES) - -test/test_vectors3: test/test_vectors.c $(KECCAK_SOURCES) $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ - -o $@ $< $(KECCAK_SOURCES) - -test/test_vectors5: test/test_vectors.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ - -o $@ $< $(KECCAK_SOURCES) - -test/test_speed2: test/test_speed.c test/speed_print.c test/speed_print.h \ - test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ - -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ - $(KECCAK_SOURCES) - -test/test_speed3: test/test_speed.c test/speed_print.c test/speed_print.h \ - test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ - -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ - $(KECCAK_SOURCES) - -test/test_speed5: test/test_speed.c test/speed_print.c test/speed_print.h \ - test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ - -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ - $(KECCAK_SOURCES) - -test/test_mul: test/test_mul.c randombytes.c $(KECCAK_SOURCES) $(KECCAK_HEADERS) - $(CC) $(CFLAGS) -UDBENCH -o $@ $< randombytes.c $(KECCAK_SOURCES) - -nistkat/PQCgenKAT_sign2: nistkat/PQCgenKAT_sign.c nistkat/rng.c nistkat/rng.h $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(NISTFLAGS) -DDILITHIUM_MODE=2 \ - -o $@ $< nistkat/rng.c $(KECCAK_SOURCES) $(LDFLAGS) -lcrypto - -nistkat/PQCgenKAT_sign3: nistkat/PQCgenKAT_sign.c nistkat/rng.c nistkat/rng.h $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(NISTFLAGS) -DDILITHIUM_MODE=3 \ - -o $@ $< nistkat/rng.c $(KECCAK_SOURCES) $(LDFLAGS) -lcrypto - -nistkat/PQCgenKAT_sign5: nistkat/PQCgenKAT_sign.c nistkat/rng.c nistkat/rng.h $(KECCAK_SOURCES) \ - $(KECCAK_HEADERS) - $(CC) $(NISTFLAGS) -DDILITHIUM_MODE=5 \ - -o $@ $< nistkat/rng.c $(KECCAK_SOURCES) $(LDFLAGS) -lcrypto - -clean: - rm -f *~ test/*~ *.gcno *.gcda *.lcov - rm -f libpqcrystals_dilithium2_ref.so - rm -f libpqcrystals_dilithium3_ref.so - rm -f libpqcrystals_dilithium5_ref.so - rm -f libpqcrystals_fips202_ref.so - rm -f test/test_dilithium2 - rm -f test/test_dilithium3 - rm -f test/test_dilithium5 - rm -f test/test_vectors2 - rm -f test/test_vectors3 - rm -f test/test_vectors5 - rm -f test/test_speed2 - rm -f test/test_speed3 - rm -f test/test_speed5 - rm -f test/test_mul - rm -f nistkat/PQCgenKAT_sign2 - rm -f nistkat/PQCgenKAT_sign3 - rm -f nistkat/PQCgenKAT_sign5 diff --git a/dilithium/ref/api.h b/dilithium/ref/api.h deleted file mode 100644 index 032fa9f..0000000 --- a/dilithium/ref/api.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef API_H -#define API_H - -#include -#include - -#define pqcrystals_dilithium2_PUBLICKEYBYTES 1312 -#define pqcrystals_dilithium2_SECRETKEYBYTES 2560 -#define pqcrystals_dilithium2_BYTES 2420 - -#define pqcrystals_dilithium2_ref_PUBLICKEYBYTES pqcrystals_dilithium2_PUBLICKEYBYTES -#define pqcrystals_dilithium2_ref_SECRETKEYBYTES pqcrystals_dilithium2_SECRETKEYBYTES -#define pqcrystals_dilithium2_ref_BYTES pqcrystals_dilithium2_BYTES - -int pqcrystals_dilithium2_ref_keypair(uint8_t *pk, uint8_t *sk); - -int pqcrystals_dilithium2_ref_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium2_ref(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium2_ref_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - -int pqcrystals_dilithium2_ref_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - -#define pqcrystals_dilithium3_PUBLICKEYBYTES 1952 -#define pqcrystals_dilithium3_SECRETKEYBYTES 4032 -#define pqcrystals_dilithium3_BYTES 3309 - -#define pqcrystals_dilithium3_ref_PUBLICKEYBYTES pqcrystals_dilithium3_PUBLICKEYBYTES -#define pqcrystals_dilithium3_ref_SECRETKEYBYTES pqcrystals_dilithium3_SECRETKEYBYTES -#define pqcrystals_dilithium3_ref_BYTES pqcrystals_dilithium3_BYTES - -int pqcrystals_dilithium3_ref_keypair(uint8_t *pk, uint8_t *sk); - -int pqcrystals_dilithium3_ref_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium3_ref(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium3_ref_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - -int pqcrystals_dilithium3_ref_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - -#define pqcrystals_dilithium5_PUBLICKEYBYTES 2592 -#define pqcrystals_dilithium5_SECRETKEYBYTES 4896 -#define pqcrystals_dilithium5_BYTES 4627 - -#define pqcrystals_dilithium5_ref_PUBLICKEYBYTES pqcrystals_dilithium5_PUBLICKEYBYTES -#define pqcrystals_dilithium5_ref_SECRETKEYBYTES pqcrystals_dilithium5_SECRETKEYBYTES -#define pqcrystals_dilithium5_ref_BYTES pqcrystals_dilithium5_BYTES - -int pqcrystals_dilithium5_ref_keypair(uint8_t *pk, uint8_t *sk); - -int pqcrystals_dilithium5_ref_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium5_ref(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -int pqcrystals_dilithium5_ref_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - -int pqcrystals_dilithium5_ref_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - - -#endif diff --git a/dilithium/ref/config.h b/dilithium/ref/config.h deleted file mode 100644 index 8469015..0000000 --- a/dilithium/ref/config.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -//#define DILITHIUM_MODE 2 -#define DILITHIUM_RANDOMIZED_SIGNING -//#define USE_RDPMC -//#define DBENCH - -#ifndef DILITHIUM_MODE -#define DILITHIUM_MODE 2 -#endif - -#if DILITHIUM_MODE == 2 -#define CRYPTO_ALGNAME_DILITHIUM "Dilithium2" -#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium2_ref -#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium2_ref_##s -#elif DILITHIUM_MODE == 3 -#define CRYPTO_ALGNAME_DILITHIUM "Dilithium3" -#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium3_ref -#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium3_ref_##s -#elif DILITHIUM_MODE == 5 -#define CRYPTO_ALGNAME_DILITHIUM "Dilithium5" -#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium5_ref -#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium5_ref_##s -#endif - -#endif diff --git a/dilithium/ref/fips202.c b/dilithium/ref/fips202.c deleted file mode 100644 index 2afe799..0000000 --- a/dilithium/ref/fips202.c +++ /dev/null @@ -1,774 +0,0 @@ -/* Based on the public domain implementation in crypto_hash/keccakc512/simple/ from - * http://bench.cr.yp.to/supercop.html by Ronny Van Keer and the public domain "TweetFips202" - * implementation from https://twitter.com/tweetfips202 by Gilles Van Assche, Daniel J. Bernstein, - * and Peter Schwabe */ - -#include -#include -#include "fips202.h" - -#define NROUNDS 24 -#define ROL(a, offset) ((a << offset) ^ (a >> (64-offset))) - -/************************************************* -* Name: load64 -* -* Description: Load 8 bytes into uint64_t in little-endian order -* -* Arguments: - const uint8_t *x: pointer to input byte array -* -* Returns the loaded 64-bit unsigned integer -**************************************************/ -static uint64_t load64(const uint8_t x[8]) { - unsigned int i; - uint64_t r = 0; - - for(i=0;i<8;i++) - r |= (uint64_t)x[i] << 8*i; - - return r; -} - -/************************************************* -* Name: store64 -* -* Description: Store a 64-bit integer to array of 8 bytes in little-endian order -* -* Arguments: - uint8_t *x: pointer to the output byte array (allocated) -* - uint64_t u: input 64-bit unsigned integer -**************************************************/ -static void store64(uint8_t x[8], uint64_t u) { - unsigned int i; - - for(i=0;i<8;i++) - x[i] = u >> 8*i; -} - -/* Keccak round constants */ -const uint64_t KeccakF_RoundConstants[NROUNDS] = { - (uint64_t)0x0000000000000001ULL, - (uint64_t)0x0000000000008082ULL, - (uint64_t)0x800000000000808aULL, - (uint64_t)0x8000000080008000ULL, - (uint64_t)0x000000000000808bULL, - (uint64_t)0x0000000080000001ULL, - (uint64_t)0x8000000080008081ULL, - (uint64_t)0x8000000000008009ULL, - (uint64_t)0x000000000000008aULL, - (uint64_t)0x0000000000000088ULL, - (uint64_t)0x0000000080008009ULL, - (uint64_t)0x000000008000000aULL, - (uint64_t)0x000000008000808bULL, - (uint64_t)0x800000000000008bULL, - (uint64_t)0x8000000000008089ULL, - (uint64_t)0x8000000000008003ULL, - (uint64_t)0x8000000000008002ULL, - (uint64_t)0x8000000000000080ULL, - (uint64_t)0x000000000000800aULL, - (uint64_t)0x800000008000000aULL, - (uint64_t)0x8000000080008081ULL, - (uint64_t)0x8000000000008080ULL, - (uint64_t)0x0000000080000001ULL, - (uint64_t)0x8000000080008008ULL -}; - -/************************************************* -* Name: KeccakF1600_StatePermute -* -* Description: The Keccak F1600 Permutation -* -* Arguments: - uint64_t *state: pointer to input/output Keccak state -**************************************************/ -static void KeccakF1600_StatePermute(uint64_t state[25]) -{ - int round; - - uint64_t Aba, Abe, Abi, Abo, Abu; - uint64_t Aga, Age, Agi, Ago, Agu; - uint64_t Aka, Ake, Aki, Ako, Aku; - uint64_t Ama, Ame, Ami, Amo, Amu; - uint64_t Asa, Ase, Asi, Aso, Asu; - uint64_t BCa, BCe, BCi, BCo, BCu; - uint64_t Da, De, Di, Do, Du; - uint64_t Eba, Ebe, Ebi, Ebo, Ebu; - uint64_t Ega, Ege, Egi, Ego, Egu; - uint64_t Eka, Eke, Eki, Eko, Eku; - uint64_t Ema, Eme, Emi, Emo, Emu; - uint64_t Esa, Ese, Esi, Eso, Esu; - - //copyFromState(A, state) - Aba = state[ 0]; - Abe = state[ 1]; - Abi = state[ 2]; - Abo = state[ 3]; - Abu = state[ 4]; - Aga = state[ 5]; - Age = state[ 6]; - Agi = state[ 7]; - Ago = state[ 8]; - Agu = state[ 9]; - Aka = state[10]; - Ake = state[11]; - Aki = state[12]; - Ako = state[13]; - Aku = state[14]; - Ama = state[15]; - Ame = state[16]; - Ami = state[17]; - Amo = state[18]; - Amu = state[19]; - Asa = state[20]; - Ase = state[21]; - Asi = state[22]; - Aso = state[23]; - Asu = state[24]; - - for(round = 0; round < NROUNDS; round += 2) { - // prepareTheta - BCa = Aba^Aga^Aka^Ama^Asa; - BCe = Abe^Age^Ake^Ame^Ase; - BCi = Abi^Agi^Aki^Ami^Asi; - BCo = Abo^Ago^Ako^Amo^Aso; - BCu = Abu^Agu^Aku^Amu^Asu; - - //thetaRhoPiChiIotaPrepareTheta(round, A, E) - Da = BCu^ROL(BCe, 1); - De = BCa^ROL(BCi, 1); - Di = BCe^ROL(BCo, 1); - Do = BCi^ROL(BCu, 1); - Du = BCo^ROL(BCa, 1); - - Aba ^= Da; - BCa = Aba; - Age ^= De; - BCe = ROL(Age, 44); - Aki ^= Di; - BCi = ROL(Aki, 43); - Amo ^= Do; - BCo = ROL(Amo, 21); - Asu ^= Du; - BCu = ROL(Asu, 14); - Eba = BCa ^((~BCe)& BCi ); - Eba ^= (uint64_t)KeccakF_RoundConstants[round]; - Ebe = BCe ^((~BCi)& BCo ); - Ebi = BCi ^((~BCo)& BCu ); - Ebo = BCo ^((~BCu)& BCa ); - Ebu = BCu ^((~BCa)& BCe ); - - Abo ^= Do; - BCa = ROL(Abo, 28); - Agu ^= Du; - BCe = ROL(Agu, 20); - Aka ^= Da; - BCi = ROL(Aka, 3); - Ame ^= De; - BCo = ROL(Ame, 45); - Asi ^= Di; - BCu = ROL(Asi, 61); - Ega = BCa ^((~BCe)& BCi ); - Ege = BCe ^((~BCi)& BCo ); - Egi = BCi ^((~BCo)& BCu ); - Ego = BCo ^((~BCu)& BCa ); - Egu = BCu ^((~BCa)& BCe ); - - Abe ^= De; - BCa = ROL(Abe, 1); - Agi ^= Di; - BCe = ROL(Agi, 6); - Ako ^= Do; - BCi = ROL(Ako, 25); - Amu ^= Du; - BCo = ROL(Amu, 8); - Asa ^= Da; - BCu = ROL(Asa, 18); - Eka = BCa ^((~BCe)& BCi ); - Eke = BCe ^((~BCi)& BCo ); - Eki = BCi ^((~BCo)& BCu ); - Eko = BCo ^((~BCu)& BCa ); - Eku = BCu ^((~BCa)& BCe ); - - Abu ^= Du; - BCa = ROL(Abu, 27); - Aga ^= Da; - BCe = ROL(Aga, 36); - Ake ^= De; - BCi = ROL(Ake, 10); - Ami ^= Di; - BCo = ROL(Ami, 15); - Aso ^= Do; - BCu = ROL(Aso, 56); - Ema = BCa ^((~BCe)& BCi ); - Eme = BCe ^((~BCi)& BCo ); - Emi = BCi ^((~BCo)& BCu ); - Emo = BCo ^((~BCu)& BCa ); - Emu = BCu ^((~BCa)& BCe ); - - Abi ^= Di; - BCa = ROL(Abi, 62); - Ago ^= Do; - BCe = ROL(Ago, 55); - Aku ^= Du; - BCi = ROL(Aku, 39); - Ama ^= Da; - BCo = ROL(Ama, 41); - Ase ^= De; - BCu = ROL(Ase, 2); - Esa = BCa ^((~BCe)& BCi ); - Ese = BCe ^((~BCi)& BCo ); - Esi = BCi ^((~BCo)& BCu ); - Eso = BCo ^((~BCu)& BCa ); - Esu = BCu ^((~BCa)& BCe ); - - // prepareTheta - BCa = Eba^Ega^Eka^Ema^Esa; - BCe = Ebe^Ege^Eke^Eme^Ese; - BCi = Ebi^Egi^Eki^Emi^Esi; - BCo = Ebo^Ego^Eko^Emo^Eso; - BCu = Ebu^Egu^Eku^Emu^Esu; - - //thetaRhoPiChiIotaPrepareTheta(round+1, E, A) - Da = BCu^ROL(BCe, 1); - De = BCa^ROL(BCi, 1); - Di = BCe^ROL(BCo, 1); - Do = BCi^ROL(BCu, 1); - Du = BCo^ROL(BCa, 1); - - Eba ^= Da; - BCa = Eba; - Ege ^= De; - BCe = ROL(Ege, 44); - Eki ^= Di; - BCi = ROL(Eki, 43); - Emo ^= Do; - BCo = ROL(Emo, 21); - Esu ^= Du; - BCu = ROL(Esu, 14); - Aba = BCa ^((~BCe)& BCi ); - Aba ^= (uint64_t)KeccakF_RoundConstants[round+1]; - Abe = BCe ^((~BCi)& BCo ); - Abi = BCi ^((~BCo)& BCu ); - Abo = BCo ^((~BCu)& BCa ); - Abu = BCu ^((~BCa)& BCe ); - - Ebo ^= Do; - BCa = ROL(Ebo, 28); - Egu ^= Du; - BCe = ROL(Egu, 20); - Eka ^= Da; - BCi = ROL(Eka, 3); - Eme ^= De; - BCo = ROL(Eme, 45); - Esi ^= Di; - BCu = ROL(Esi, 61); - Aga = BCa ^((~BCe)& BCi ); - Age = BCe ^((~BCi)& BCo ); - Agi = BCi ^((~BCo)& BCu ); - Ago = BCo ^((~BCu)& BCa ); - Agu = BCu ^((~BCa)& BCe ); - - Ebe ^= De; - BCa = ROL(Ebe, 1); - Egi ^= Di; - BCe = ROL(Egi, 6); - Eko ^= Do; - BCi = ROL(Eko, 25); - Emu ^= Du; - BCo = ROL(Emu, 8); - Esa ^= Da; - BCu = ROL(Esa, 18); - Aka = BCa ^((~BCe)& BCi ); - Ake = BCe ^((~BCi)& BCo ); - Aki = BCi ^((~BCo)& BCu ); - Ako = BCo ^((~BCu)& BCa ); - Aku = BCu ^((~BCa)& BCe ); - - Ebu ^= Du; - BCa = ROL(Ebu, 27); - Ega ^= Da; - BCe = ROL(Ega, 36); - Eke ^= De; - BCi = ROL(Eke, 10); - Emi ^= Di; - BCo = ROL(Emi, 15); - Eso ^= Do; - BCu = ROL(Eso, 56); - Ama = BCa ^((~BCe)& BCi ); - Ame = BCe ^((~BCi)& BCo ); - Ami = BCi ^((~BCo)& BCu ); - Amo = BCo ^((~BCu)& BCa ); - Amu = BCu ^((~BCa)& BCe ); - - Ebi ^= Di; - BCa = ROL(Ebi, 62); - Ego ^= Do; - BCe = ROL(Ego, 55); - Eku ^= Du; - BCi = ROL(Eku, 39); - Ema ^= Da; - BCo = ROL(Ema, 41); - Ese ^= De; - BCu = ROL(Ese, 2); - Asa = BCa ^((~BCe)& BCi ); - Ase = BCe ^((~BCi)& BCo ); - Asi = BCi ^((~BCo)& BCu ); - Aso = BCo ^((~BCu)& BCa ); - Asu = BCu ^((~BCa)& BCe ); - } - - //copyToState(state, A) - state[ 0] = Aba; - state[ 1] = Abe; - state[ 2] = Abi; - state[ 3] = Abo; - state[ 4] = Abu; - state[ 5] = Aga; - state[ 6] = Age; - state[ 7] = Agi; - state[ 8] = Ago; - state[ 9] = Agu; - state[10] = Aka; - state[11] = Ake; - state[12] = Aki; - state[13] = Ako; - state[14] = Aku; - state[15] = Ama; - state[16] = Ame; - state[17] = Ami; - state[18] = Amo; - state[19] = Amu; - state[20] = Asa; - state[21] = Ase; - state[22] = Asi; - state[23] = Aso; - state[24] = Asu; -} - -/************************************************* -* Name: keccak_init -* -* Description: Initializes the Keccak state. -* -* Arguments: - uint64_t *s: pointer to Keccak state -**************************************************/ -static void keccak_init(uint64_t s[25]) -{ - unsigned int i; - for(i=0;i<25;i++) - s[i] = 0; -} - -/************************************************* -* Name: keccak_absorb -* -* Description: Absorb step of Keccak; incremental. -* -* Arguments: - uint64_t *s: pointer to Keccak state -* - unsigned int pos: position in current block to be absorbed -* - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) -* - const uint8_t *in: pointer to input to be absorbed into s -* - size_t inlen: length of input in bytes -* -* Returns new position pos in current block -**************************************************/ -static unsigned int keccak_absorb(uint64_t s[25], - unsigned int pos, - unsigned int r, - const uint8_t *in, - size_t inlen) -{ - unsigned int i; - - while(pos+inlen >= r) { - for(i=pos;i> 8*(i%8); - outlen -= i-pos; - pos = i; - } - - return pos; -} - - -/************************************************* -* Name: keccak_absorb_once -* -* Description: Absorb step of Keccak; -* non-incremental, starts by zeroeing the state. -* -* Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state -* - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) -* - const uint8_t *in: pointer to input to be absorbed into s -* - size_t inlen: length of input in bytes -* - uint8_t p: domain-separation byte for different Keccak-derived functions -**************************************************/ -static void keccak_absorb_once(uint64_t s[25], - unsigned int r, - const uint8_t *in, - size_t inlen, - uint8_t p) -{ - unsigned int i; - - for(i=0;i<25;i++) - s[i] = 0; - - while(inlen >= r) { - for(i=0;is); - state->pos = 0; -} - -/************************************************* -* Name: shake128_absorb -* -* Description: Absorb step of the SHAKE128 XOF; incremental. -* -* Arguments: - keccak_state *state: pointer to (initialized) output Keccak state -* - const uint8_t *in: pointer to input to be absorbed into s -* - size_t inlen: length of input in bytes -**************************************************/ -void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen) -{ - state->pos = keccak_absorb(state->s, state->pos, SHAKE128_RATE, in, inlen); -} - -/************************************************* -* Name: shake128_finalize -* -* Description: Finalize absorb step of the SHAKE128 XOF. -* -* Arguments: - keccak_state *state: pointer to Keccak state -**************************************************/ -void shake128_finalize(keccak_state *state) -{ - keccak_finalize(state->s, state->pos, SHAKE128_RATE, 0x1F); - state->pos = SHAKE128_RATE; -} - -/************************************************* -* Name: shake128_squeeze -* -* Description: Squeeze step of SHAKE128 XOF. Squeezes arbitraily many -* bytes. Can be called multiple times to keep squeezing. -* -* Arguments: - uint8_t *out: pointer to output blocks -* - size_t outlen : number of bytes to be squeezed (written to output) -* - keccak_state *s: pointer to input/output Keccak state -**************************************************/ -void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state) -{ - state->pos = keccak_squeeze(out, outlen, state->s, state->pos, SHAKE128_RATE); -} - -/************************************************* -* Name: shake128_absorb_once -* -* Description: Initialize, absorb into and finalize SHAKE128 XOF; non-incremental. -* -* Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak state -* - const uint8_t *in: pointer to input to be absorbed into s -* - size_t inlen: length of input in bytes -**************************************************/ -void shake128_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen) -{ - keccak_absorb_once(state->s, SHAKE128_RATE, in, inlen, 0x1F); - state->pos = SHAKE128_RATE; -} - -/************************************************* -* Name: shake128_squeezeblocks -* -* Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of -* SHAKE128_RATE bytes each. Can be called multiple times -* to keep squeezing. Assumes new block has not yet been -* started (state->pos = SHAKE128_RATE). -* -* Arguments: - uint8_t *out: pointer to output blocks -* - size_t nblocks: number of blocks to be squeezed (written to output) -* - keccak_state *s: pointer to input/output Keccak state -**************************************************/ -void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) -{ - keccak_squeezeblocks(out, nblocks, state->s, SHAKE128_RATE); -} - -/************************************************* -* Name: shake256_init -* -* Description: Initilizes Keccak state for use as SHAKE256 XOF -* -* Arguments: - keccak_state *state: pointer to (uninitialized) Keccak state -**************************************************/ -void shake256_init(keccak_state *state) -{ - keccak_init(state->s); - state->pos = 0; -} - -/************************************************* -* Name: shake256_absorb -* -* Description: Absorb step of the SHAKE256 XOF; incremental. -* -* Arguments: - keccak_state *state: pointer to (initialized) output Keccak state -* - const uint8_t *in: pointer to input to be absorbed into s -* - size_t inlen: length of input in bytes -**************************************************/ -void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen) -{ - state->pos = keccak_absorb(state->s, state->pos, SHAKE256_RATE, in, inlen); -} - -/************************************************* -* Name: shake256_finalize -* -* Description: Finalize absorb step of the SHAKE256 XOF. -* -* Arguments: - keccak_state *state: pointer to Keccak state -**************************************************/ -void shake256_finalize(keccak_state *state) -{ - keccak_finalize(state->s, state->pos, SHAKE256_RATE, 0x1F); - state->pos = SHAKE256_RATE; -} - -/************************************************* -* Name: shake256_squeeze -* -* Description: Squeeze step of SHAKE256 XOF. Squeezes arbitraily many -* bytes. Can be called multiple times to keep squeezing. -* -* Arguments: - uint8_t *out: pointer to output blocks -* - size_t outlen : number of bytes to be squeezed (written to output) -* - keccak_state *s: pointer to input/output Keccak state -**************************************************/ -void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state) -{ - state->pos = keccak_squeeze(out, outlen, state->s, state->pos, SHAKE256_RATE); -} - -/************************************************* -* Name: shake256_absorb_once -* -* Description: Initialize, absorb into and finalize SHAKE256 XOF; non-incremental. -* -* Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak state -* - const uint8_t *in: pointer to input to be absorbed into s -* - size_t inlen: length of input in bytes -**************************************************/ -void shake256_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen) -{ - keccak_absorb_once(state->s, SHAKE256_RATE, in, inlen, 0x1F); - state->pos = SHAKE256_RATE; -} - -/************************************************* -* Name: shake256_squeezeblocks -* -* Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of -* SHAKE256_RATE bytes each. Can be called multiple times -* to keep squeezing. Assumes next block has not yet been -* started (state->pos = SHAKE256_RATE). -* -* Arguments: - uint8_t *out: pointer to output blocks -* - size_t nblocks: number of blocks to be squeezed (written to output) -* - keccak_state *s: pointer to input/output Keccak state -**************************************************/ -void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) -{ - keccak_squeezeblocks(out, nblocks, state->s, SHAKE256_RATE); -} - -/************************************************* -* Name: shake128 -* -* Description: SHAKE128 XOF with non-incremental API -* -* Arguments: - uint8_t *out: pointer to output -* - size_t outlen: requested output length in bytes -* - const uint8_t *in: pointer to input -* - size_t inlen: length of input in bytes -**************************************************/ -void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) -{ - size_t nblocks; - keccak_state state; - - shake128_absorb_once(&state, in, inlen); - nblocks = outlen/SHAKE128_RATE; - shake128_squeezeblocks(out, nblocks, &state); - outlen -= nblocks*SHAKE128_RATE; - out += nblocks*SHAKE128_RATE; - shake128_squeeze(out, outlen, &state); -} - -/************************************************* -* Name: shake256 -* -* Description: SHAKE256 XOF with non-incremental API -* -* Arguments: - uint8_t *out: pointer to output -* - size_t outlen: requested output length in bytes -* - const uint8_t *in: pointer to input -* - size_t inlen: length of input in bytes -**************************************************/ -void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) -{ - size_t nblocks; - keccak_state state; - - shake256_absorb_once(&state, in, inlen); - nblocks = outlen/SHAKE256_RATE; - shake256_squeezeblocks(out, nblocks, &state); - outlen -= nblocks*SHAKE256_RATE; - out += nblocks*SHAKE256_RATE; - shake256_squeeze(out, outlen, &state); -} - -/************************************************* -* Name: sha3_256 -* -* Description: SHA3-256 with non-incremental API -* -* Arguments: - uint8_t *h: pointer to output (32 bytes) -* - const uint8_t *in: pointer to input -* - size_t inlen: length of input in bytes -**************************************************/ -void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen) -{ - unsigned int i; - uint64_t s[25]; - - keccak_absorb_once(s, SHA3_256_RATE, in, inlen, 0x06); - KeccakF1600_StatePermute(s); - for(i=0;i<4;i++) - store64(h+8*i,s[i]); -} - -/************************************************* -* Name: sha3_512 -* -* Description: SHA3-512 with non-incremental API -* -* Arguments: - uint8_t *h: pointer to output (64 bytes) -* - const uint8_t *in: pointer to input -* - size_t inlen: length of input in bytes -**************************************************/ -void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen) -{ - unsigned int i; - uint64_t s[25]; - - keccak_absorb_once(s, SHA3_512_RATE, in, inlen, 0x06); - KeccakF1600_StatePermute(s); - for(i=0;i<8;i++) - store64(h+8*i,s[i]); -} diff --git a/dilithium/ref/fips202.h b/dilithium/ref/fips202.h deleted file mode 100644 index c37f535..0000000 --- a/dilithium/ref/fips202.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef FIPS202_H -#define FIPS202_H - -#include -#include - -#define SHAKE128_RATE 168 -#define SHAKE256_RATE 136 -#define SHA3_256_RATE 136 -#define SHA3_512_RATE 72 - -#define FIPS202_NAMESPACE(s) pqcrystals_dilithium_fips202_ref_##s - -typedef struct { - uint64_t s[25]; - unsigned int pos; -} keccak_state; - -#define KeccakF_RoundConstants FIPS202_NAMESPACE(KeccakF_RoundConstants) -extern const uint64_t KeccakF_RoundConstants[]; - -#define shake128_init FIPS202_NAMESPACE(shake128_init) -void shake128_init(keccak_state *state); -#define shake128_absorb FIPS202_NAMESPACE(shake128_absorb) -void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake128_finalize FIPS202_NAMESPACE(shake128_finalize) -void shake128_finalize(keccak_state *state); -#define shake128_squeeze FIPS202_NAMESPACE(shake128_squeeze) -void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state); -#define shake128_absorb_once FIPS202_NAMESPACE(shake128_absorb_once) -void shake128_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake128_squeezeblocks FIPS202_NAMESPACE(shake128_squeezeblocks) -void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); - -#define shake256_init FIPS202_NAMESPACE(shake256_init) -void shake256_init(keccak_state *state); -#define shake256_absorb FIPS202_NAMESPACE(shake256_absorb) -void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake256_finalize FIPS202_NAMESPACE(shake256_finalize) -void shake256_finalize(keccak_state *state); -#define shake256_squeeze FIPS202_NAMESPACE(shake256_squeeze) -void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state); -#define shake256_absorb_once FIPS202_NAMESPACE(shake256_absorb_once) -void shake256_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake256_squeezeblocks FIPS202_NAMESPACE(shake256_squeezeblocks) -void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); - -#define shake128 FIPS202_NAMESPACE(shake128) -void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); -#define shake256 FIPS202_NAMESPACE(shake256) -void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); -#define sha3_256 FIPS202_NAMESPACE(sha3_256) -void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen); -#define sha3_512 FIPS202_NAMESPACE(sha3_512) -void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen); - -#endif diff --git a/dilithium/ref/nistkat/.gitignore b/dilithium/ref/nistkat/.gitignore deleted file mode 100644 index 0aa8057..0000000 --- a/dilithium/ref/nistkat/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -PQCgenKAT_sign2 -PQCgenKAT_sign3 -PQCgenKAT_sign5 diff --git a/dilithium/ref/nistkat/PQCgenKAT_sign.c b/dilithium/ref/nistkat/PQCgenKAT_sign.c deleted file mode 100644 index 005ce41..0000000 --- a/dilithium/ref/nistkat/PQCgenKAT_sign.c +++ /dev/null @@ -1,261 +0,0 @@ -// -// PQCgenKAT_sign.c -// -// Created by Bassham, Lawrence E (Fed) on 8/29/17. -// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. -// -#include -#include -#include -#include -#include -#include "rng.h" -#include "../sign.h" - -#define MAX_MARKER_LEN 50 - -#define KAT_SUCCESS 0 -#define KAT_FILE_OPEN_ERROR -1 -#define KAT_DATA_ERROR -3 -#define KAT_CRYPTO_FAILURE -4 - -int FindMarker(FILE *infile, const char *marker); -int ReadHex(FILE *infile, unsigned char *a, int Length, char *str); -void fprintBstr(FILE *fp, char *s, unsigned char *a, unsigned long long l); - -int -main() -{ - char fn_req[32], fn_rsp[32]; - FILE *fp_req, *fp_rsp; - uint8_t seed[48]; - uint8_t msg[3300]; - uint8_t entropy_input[48]; - uint8_t *m, *sm, *m1; - size_t mlen, smlen, mlen1; - int count; - int done; - uint8_t pk[CRYPTO_PUBLICKEYBYTES], sk[CRYPTO_SECRETKEYBYTES]; - int ret_val; - - // Create the REQUEST file - sprintf(fn_req, "PQCsignKAT_%.16s.req", CRYPTO_ALGNAME); - if ( (fp_req = fopen(fn_req, "w")) == NULL ) { - printf("Couldn't open <%s> for write\n", fn_req); - return KAT_FILE_OPEN_ERROR; - } - sprintf(fn_rsp, "PQCsignKAT_%.16s.rsp", CRYPTO_ALGNAME); - if ( (fp_rsp = fopen(fn_rsp, "w")) == NULL ) { - printf("Couldn't open <%s> for write\n", fn_rsp); - return KAT_FILE_OPEN_ERROR; - } - - for (int i=0; i<48; i++) - entropy_input[i] = i; - - randombytes_init(entropy_input, NULL, 256); - for (int i=0; i<100; i++) { - fprintf(fp_req, "count = %d\n", i); - randombytes(seed, 48); - fprintBstr(fp_req, "seed = ", seed, 48); - mlen = 33*(i+1); - fprintf(fp_req, "mlen = %lu\n", mlen); - randombytes(msg, mlen); - fprintBstr(fp_req, "msg = ", msg, mlen); - fprintf(fp_req, "pk =\n"); - fprintf(fp_req, "sk =\n"); - fprintf(fp_req, "smlen =\n"); - fprintf(fp_req, "sm =\n\n"); - } - fclose(fp_req); - - //Create the RESPONSE file based on what's in the REQUEST file - if ( (fp_req = fopen(fn_req, "r")) == NULL ) { - printf("Couldn't open <%s> for read\n", fn_req); - return KAT_FILE_OPEN_ERROR; - } - - fprintf(fp_rsp, "# %s\n\n", CRYPTO_ALGNAME); - done = 0; - do { - if ( FindMarker(fp_req, "count = ") ) - fscanf(fp_req, "%d", &count); - else { - done = 1; - break; - } - fprintf(fp_rsp, "count = %d\n", count); - - if ( !ReadHex(fp_req, seed, 48, "seed = ") ) { - printf("ERROR: unable to read 'seed' from <%s>\n", fn_req); - return KAT_DATA_ERROR; - } - fprintBstr(fp_rsp, "seed = ", seed, 48); - - randombytes_init(seed, NULL, 256); - - if ( FindMarker(fp_req, "mlen = ") ) - fscanf(fp_req, "%lu", &mlen); - else { - printf("ERROR: unable to read 'mlen' from <%s>\n", fn_req); - return KAT_DATA_ERROR; - } - fprintf(fp_rsp, "mlen = %lu\n", mlen); - - m = (uint8_t *)calloc(mlen, sizeof(uint8_t)); - m1 = (uint8_t *)calloc(mlen+CRYPTO_BYTES, sizeof(uint8_t)); - sm = (uint8_t *)calloc(mlen+CRYPTO_BYTES, sizeof(uint8_t)); - - if ( !ReadHex(fp_req, m, (int)mlen, "msg = ") ) { - printf("ERROR: unable to read 'msg' from <%s>\n", fn_req); - return KAT_DATA_ERROR; - } - fprintBstr(fp_rsp, "msg = ", m, mlen); - - // Generate the public/private keypair - if ( (ret_val = crypto_sign_keypair(pk, sk)) != 0) { - printf("crypto_sign_keypair returned <%d>\n", ret_val); - return KAT_CRYPTO_FAILURE; - } - fprintBstr(fp_rsp, "pk = ", pk, CRYPTO_PUBLICKEYBYTES); - fprintBstr(fp_rsp, "sk = ", sk, CRYPTO_SECRETKEYBYTES); - - if ( (ret_val = crypto_sign(sm, &smlen, m, mlen, NULL, 0, sk)) != 0) { - printf("crypto_sign returned <%d>\n", ret_val); - return KAT_CRYPTO_FAILURE; - } - fprintf(fp_rsp, "smlen = %lu\n", smlen); - fprintBstr(fp_rsp, "sm = ", sm, smlen); - fprintf(fp_rsp, "\n"); - - if ( (ret_val = crypto_sign_open(m1, &mlen1, sm, smlen, NULL, 0, pk)) != 0) { - printf("crypto_sign_open returned <%d>\n", ret_val); - return KAT_CRYPTO_FAILURE; - } - - if ( mlen != mlen1 ) { - printf("crypto_sign_open returned bad 'mlen': Got <%lu>, expected <%lu>\n", mlen1, mlen); - return KAT_CRYPTO_FAILURE; - } - - if ( memcmp(m, m1, mlen) ) { - printf("crypto_sign_open returned bad 'm' value\n"); - return KAT_CRYPTO_FAILURE; - } - - free(m); - free(m1); - free(sm); - - } while ( !done ); - - fclose(fp_req); - fclose(fp_rsp); - - return KAT_SUCCESS; -} - -// -// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.) -// -int -FindMarker(FILE *infile, const char *marker) -{ - char line[MAX_MARKER_LEN]; - int i, len; - int curr_line; - - len = (int)strlen(marker); - if ( len > MAX_MARKER_LEN-1 ) - len = MAX_MARKER_LEN-1; - - for ( i=0; i= '0') && (ch <= '9') ) - ich = ch - '0'; - else if ( (ch >= 'A') && (ch <= 'F') ) - ich = ch - 'A' + 10; - else if ( (ch >= 'a') && (ch <= 'f') ) - ich = ch - 'a' + 10; - else // shouldn't ever get here - ich = 0; - - for ( i=0; i> 4); - a[Length-1] = (a[Length-1] << 4) | ich; - } - else - return 0; - - return 1; -} - -void -fprintBstr(FILE *fp, char *s, unsigned char *a, unsigned long long l) -{ - unsigned long long i; - - fprintf(fp, "%s", s); - - for ( i=0; i -#include "rng.h" -#include -#include -#include - -AES256_CTR_DRBG_struct DRBG_ctx; - -void AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer); - -/* - seedexpander_init() - ctx - stores the current state of an instance of the seed expander - seed - a 32 byte random value - diversifier - an 8 byte diversifier - maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier - */ -int -seedexpander_init(AES_XOF_struct *ctx, - unsigned char *seed, - unsigned char *diversifier, - unsigned long maxlen) -{ - if ( maxlen >= 0x100000000 ) - return RNG_BAD_MAXLEN; - - ctx->length_remaining = maxlen; - - memcpy(ctx->key, seed, 32); - - memcpy(ctx->ctr, diversifier, 8); - ctx->ctr[11] = maxlen % 256; - maxlen >>= 8; - ctx->ctr[10] = maxlen % 256; - maxlen >>= 8; - ctx->ctr[9] = maxlen % 256; - maxlen >>= 8; - ctx->ctr[8] = maxlen % 256; - memset(ctx->ctr+12, 0x00, 4); - - ctx->buffer_pos = 16; - memset(ctx->buffer, 0x00, 16); - - return RNG_SUCCESS; -} - -/* - seedexpander() - ctx - stores the current state of an instance of the seed expander - x - returns the XOF data - xlen - number of bytes to return - */ -int -seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen) -{ - unsigned long offset; - - if ( x == NULL ) - return RNG_BAD_OUTBUF; - if ( xlen >= ctx->length_remaining ) - return RNG_BAD_REQ_LEN; - - ctx->length_remaining -= xlen; - - offset = 0; - while ( xlen > 0 ) { - if ( xlen <= (16-ctx->buffer_pos) ) { // buffer has what we need - memcpy(x+offset, ctx->buffer+ctx->buffer_pos, xlen); - ctx->buffer_pos += xlen; - - return RNG_SUCCESS; - } - - // take what's in the buffer - memcpy(x+offset, ctx->buffer+ctx->buffer_pos, 16-ctx->buffer_pos); - xlen -= 16-ctx->buffer_pos; - offset += 16-ctx->buffer_pos; - - AES256_ECB(ctx->key, ctx->ctr, ctx->buffer); - ctx->buffer_pos = 0; - - //increment the counter - for (int i=15; i>=12; i--) { - if ( ctx->ctr[i] == 0xff ) - ctx->ctr[i] = 0x00; - else { - ctx->ctr[i]++; - break; - } - } - - } - - return RNG_SUCCESS; -} - - -void handleErrors(void) -{ - ERR_print_errors_fp(stderr); - abort(); -} - -// Use whatever AES implementation you have. This uses AES from openSSL library -// key - 256-bit AES key -// ctr - a 128-bit plaintext value -// buffer - a 128-bit ciphertext value -void -AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer) -{ - EVP_CIPHER_CTX *ctx; - - int len; - - int ciphertext_len; - - /* Create and initialise the context */ - if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); - - if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL)) - handleErrors(); - - if(1 != EVP_EncryptUpdate(ctx, buffer, &len, ctr, 16)) - handleErrors(); - ciphertext_len = len; - - /* Clean up */ - EVP_CIPHER_CTX_free(ctx); -} - -void -randombytes_init(unsigned char *entropy_input, - unsigned char *personalization_string, - int security_strength) -{ - unsigned char seed_material[48]; - - memcpy(seed_material, entropy_input, 48); - if (personalization_string) - for (int i=0; i<48; i++) - seed_material[i] ^= personalization_string[i]; - memset(DRBG_ctx.Key, 0x00, 32); - memset(DRBG_ctx.V, 0x00, 16); - AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V); - DRBG_ctx.reseed_counter = 1; -} - -int -randombytes(unsigned char *x, unsigned long long xlen) -{ - unsigned char block[16]; - int i = 0; - - while ( xlen > 0 ) { - //increment V - for (int j=15; j>=0; j--) { - if ( DRBG_ctx.V[j] == 0xff ) - DRBG_ctx.V[j] = 0x00; - else { - DRBG_ctx.V[j]++; - break; - } - } - AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block); - if ( xlen > 15 ) { - memcpy(x+i, block, 16); - i += 16; - xlen -= 16; - } - else { - memcpy(x+i, block, xlen); - xlen = 0; - } - } - AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V); - DRBG_ctx.reseed_counter++; - - return RNG_SUCCESS; -} - -void -AES256_CTR_DRBG_Update(unsigned char *provided_data, - unsigned char *Key, - unsigned char *V) -{ - unsigned char temp[48]; - - for (int i=0; i<3; i++) { - //increment V - for (int j=15; j>=0; j--) { - if ( V[j] == 0xff ) - V[j] = 0x00; - else { - V[j]++; - break; - } - } - - AES256_ECB(Key, V, temp+16*i); - } - if ( provided_data != NULL ) - for (int i=0; i<48; i++) - temp[i] ^= provided_data[i]; - memcpy(Key, temp, 32); - memcpy(V, temp+32, 16); -} - - - - - - - - - diff --git a/dilithium/ref/nistkat/rng.h b/dilithium/ref/nistkat/rng.h deleted file mode 100644 index 577e263..0000000 --- a/dilithium/ref/nistkat/rng.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// rng.h -// -// Created by Bassham, Lawrence E (Fed) on 8/29/17. -// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. -// - -#ifndef rng_h -#define rng_h - -#include - -#define RNG_SUCCESS 0 -#define RNG_BAD_MAXLEN -1 -#define RNG_BAD_OUTBUF -2 -#define RNG_BAD_REQ_LEN -3 - -typedef struct { - unsigned char buffer[16]; - int buffer_pos; - unsigned long length_remaining; - unsigned char key[32]; - unsigned char ctr[16]; -} AES_XOF_struct; - -typedef struct { - unsigned char Key[32]; - unsigned char V[16]; - int reseed_counter; -} AES256_CTR_DRBG_struct; - - -void -AES256_CTR_DRBG_Update(unsigned char *provided_data, - unsigned char *Key, - unsigned char *V); - -int -seedexpander_init(AES_XOF_struct *ctx, - unsigned char *seed, - unsigned char *diversifier, - unsigned long maxlen); - -int -seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen); - -void -randombytes_init(unsigned char *entropy_input, - unsigned char *personalization_string, - int security_strength); - -int -randombytes(unsigned char *x, unsigned long long xlen); - -#endif /* rng_h */ diff --git a/dilithium/ref/ntt.c b/dilithium/ref/ntt.c deleted file mode 100644 index 5ea8b53..0000000 --- a/dilithium/ref/ntt.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include "params.h" -#include "ntt.h" -#include "reduce.h" - -static const int32_t zetas[N] = { - 0, 25847, -2608894, -518909, 237124, -777960, -876248, 466468, - 1826347, 2353451, -359251, -2091905, 3119733, -2884855, 3111497, 2680103, - 2725464, 1024112, -1079900, 3585928, -549488, -1119584, 2619752, -2108549, - -2118186, -3859737, -1399561, -3277672, 1757237, -19422, 4010497, 280005, - 2706023, 95776, 3077325, 3530437, -1661693, -3592148, -2537516, 3915439, - -3861115, -3043716, 3574422, -2867647, 3539968, -300467, 2348700, -539299, - -1699267, -1643818, 3505694, -3821735, 3507263, -2140649, -1600420, 3699596, - 811944, 531354, 954230, 3881043, 3900724, -2556880, 2071892, -2797779, - -3930395, -1528703, -3677745, -3041255, -1452451, 3475950, 2176455, -1585221, - -1257611, 1939314, -4083598, -1000202, -3190144, -3157330, -3632928, 126922, - 3412210, -983419, 2147896, 2715295, -2967645, -3693493, -411027, -2477047, - -671102, -1228525, -22981, -1308169, -381987, 1349076, 1852771, -1430430, - -3343383, 264944, 508951, 3097992, 44288, -1100098, 904516, 3958618, - -3724342, -8578, 1653064, -3249728, 2389356, -210977, 759969, -1316856, - 189548, -3553272, 3159746, -1851402, -2409325, -177440, 1315589, 1341330, - 1285669, -1584928, -812732, -1439742, -3019102, -3881060, -3628969, 3839961, - 2091667, 3407706, 2316500, 3817976, -3342478, 2244091, -2446433, -3562462, - 266997, 2434439, -1235728, 3513181, -3520352, -3759364, -1197226, -3193378, - 900702, 1859098, 909542, 819034, 495491, -1613174, -43260, -522500, - -655327, -3122442, 2031748, 3207046, -3556995, -525098, -768622, -3595838, - 342297, 286988, -2437823, 4108315, 3437287, -3342277, 1735879, 203044, - 2842341, 2691481, -2590150, 1265009, 4055324, 1247620, 2486353, 1595974, - -3767016, 1250494, 2635921, -3548272, -2994039, 1869119, 1903435, -1050970, - -1333058, 1237275, -3318210, -1430225, -451100, 1312455, 3306115, -1962642, - -1279661, 1917081, -2546312, -1374803, 1500165, 777191, 2235880, 3406031, - -542412, -2831860, -1671176, -1846953, -2584293, -3724270, 594136, -3776993, - -2013608, 2432395, 2454455, -164721, 1957272, 3369112, 185531, -1207385, - -3183426, 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107, - -3038916, 3523897, 3866901, 269760, 2213111, -975884, 1717735, 472078, - -426683, 1723600, -1803090, 1910376, -1667432, -1104333, -260646, -3833893, - -2939036, -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, - -554416, 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782 -}; - -/************************************************* -* Name: ntt -* -* Description: Forward NTT, in-place. No modular reduction is performed after -* additions or subtractions. Output vector is in bitreversed order. -* -* Arguments: - uint32_t p[N]: input/output coefficient array -**************************************************/ -void ntt(int32_t a[N]) { - unsigned int len, start, j, k; - int32_t zeta, t; - - k = 0; - for(len = 128; len > 0; len >>= 1) { - for(start = 0; start < N; start = j + len) { - zeta = zetas[++k]; - for(j = start; j < start + len; ++j) { - t = montgomery_reduce((int64_t)zeta * a[j + len]); - a[j + len] = a[j] - t; - a[j] = a[j] + t; - } - } - } -} - -/************************************************* -* Name: invntt_tomont -* -* Description: Inverse NTT and multiplication by Montgomery factor 2^32. -* In-place. No modular reductions after additions or -* subtractions; input coefficients need to be smaller than -* Q in absolute value. Output coefficient are smaller than Q in -* absolute value. -* -* Arguments: - uint32_t p[N]: input/output coefficient array -**************************************************/ -void invntt_tomont(int32_t a[N]) { - unsigned int start, len, j, k; - int32_t t, zeta; - const int32_t f = 41978; // mont^2/256 - - k = 256; - for(len = 1; len < N; len <<= 1) { - for(start = 0; start < N; start = j + len) { - zeta = -zetas[--k]; - for(j = start; j < start + len; ++j) { - t = a[j]; - a[j] = t + a[j + len]; - a[j + len] = t - a[j + len]; - a[j + len] = montgomery_reduce((int64_t)zeta * a[j + len]); - } - } - } - - for(j = 0; j < N; ++j) { - a[j] = montgomery_reduce((int64_t)f * a[j]); - } -} diff --git a/dilithium/ref/ntt.h b/dilithium/ref/ntt.h deleted file mode 100644 index 731132d..0000000 --- a/dilithium/ref/ntt.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NTT_H -#define NTT_H - -#include -#include "params.h" - -#define ntt DILITHIUM_NAMESPACE(ntt) -void ntt(int32_t a[N]); - -#define invntt_tomont DILITHIUM_NAMESPACE(invntt_tomont) -void invntt_tomont(int32_t a[N]); - -#endif diff --git a/dilithium/ref/packing.c b/dilithium/ref/packing.c deleted file mode 100644 index 039a686..0000000 --- a/dilithium/ref/packing.c +++ /dev/null @@ -1,237 +0,0 @@ -#include "params.h" -#include "packing.h" -#include "polyvec.h" -#include "poly.h" - -/************************************************* -* Name: pack_pk -* -* Description: Bit-pack public key pk = (rho, t1). -* -* Arguments: - uint8_t pk[]: output byte array -* - const uint8_t rho[]: byte array containing rho -* - const polyveck *t1: pointer to vector t1 -**************************************************/ -void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], - const uint8_t rho[SEEDBYTES], - const polyveck *t1) -{ - unsigned int i; - - for(i = 0; i < SEEDBYTES; ++i) - pk[i] = rho[i]; - pk += SEEDBYTES; - - for(i = 0; i < K; ++i) - polyt1_pack(pk + i*POLYT1_PACKEDBYTES, &t1->vec[i]); -} - -/************************************************* -* Name: unpack_pk -* -* Description: Unpack public key pk = (rho, t1). -* -* Arguments: - const uint8_t rho[]: output byte array for rho -* - const polyveck *t1: pointer to output vector t1 -* - uint8_t pk[]: byte array containing bit-packed pk -**************************************************/ -void unpack_pk(uint8_t rho[SEEDBYTES], - polyveck *t1, - const uint8_t pk[CRYPTO_PUBLICKEYBYTES]) -{ - unsigned int i; - - for(i = 0; i < SEEDBYTES; ++i) - rho[i] = pk[i]; - pk += SEEDBYTES; - - for(i = 0; i < K; ++i) - polyt1_unpack(&t1->vec[i], pk + i*POLYT1_PACKEDBYTES); -} - -/************************************************* -* Name: pack_sk -* -* Description: Bit-pack secret key sk = (rho, tr, key, t0, s1, s2). -* -* Arguments: - uint8_t sk[]: output byte array -* - const uint8_t rho[]: byte array containing rho -* - const uint8_t tr[]: byte array containing tr -* - const uint8_t key[]: byte array containing key -* - const polyveck *t0: pointer to vector t0 -* - const polyvecl *s1: pointer to vector s1 -* - const polyveck *s2: pointer to vector s2 -**************************************************/ -void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], - const uint8_t rho[SEEDBYTES], - const uint8_t tr[TRBYTES], - const uint8_t key[SEEDBYTES], - const polyveck *t0, - const polyvecl *s1, - const polyveck *s2) -{ - unsigned int i; - - for(i = 0; i < SEEDBYTES; ++i) - sk[i] = rho[i]; - sk += SEEDBYTES; - - for(i = 0; i < SEEDBYTES; ++i) - sk[i] = key[i]; - sk += SEEDBYTES; - - for(i = 0; i < TRBYTES; ++i) - sk[i] = tr[i]; - sk += TRBYTES; - - for(i = 0; i < L; ++i) - polyeta_pack(sk + i*POLYETA_PACKEDBYTES, &s1->vec[i]); - sk += L*POLYETA_PACKEDBYTES; - - for(i = 0; i < K; ++i) - polyeta_pack(sk + i*POLYETA_PACKEDBYTES, &s2->vec[i]); - sk += K*POLYETA_PACKEDBYTES; - - for(i = 0; i < K; ++i) - polyt0_pack(sk + i*POLYT0_PACKEDBYTES, &t0->vec[i]); -} - -/************************************************* -* Name: unpack_sk -* -* Description: Unpack secret key sk = (rho, tr, key, t0, s1, s2). -* -* Arguments: - const uint8_t rho[]: output byte array for rho -* - const uint8_t tr[]: output byte array for tr -* - const uint8_t key[]: output byte array for key -* - const polyveck *t0: pointer to output vector t0 -* - const polyvecl *s1: pointer to output vector s1 -* - const polyveck *s2: pointer to output vector s2 -* - uint8_t sk[]: byte array containing bit-packed sk -**************************************************/ -void unpack_sk(uint8_t rho[SEEDBYTES], - uint8_t tr[TRBYTES], - uint8_t key[SEEDBYTES], - polyveck *t0, - polyvecl *s1, - polyveck *s2, - const uint8_t sk[CRYPTO_SECRETKEYBYTES]) -{ - unsigned int i; - - for(i = 0; i < SEEDBYTES; ++i) - rho[i] = sk[i]; - sk += SEEDBYTES; - - for(i = 0; i < SEEDBYTES; ++i) - key[i] = sk[i]; - sk += SEEDBYTES; - - for(i = 0; i < TRBYTES; ++i) - tr[i] = sk[i]; - sk += TRBYTES; - - for(i=0; i < L; ++i) - polyeta_unpack(&s1->vec[i], sk + i*POLYETA_PACKEDBYTES); - sk += L*POLYETA_PACKEDBYTES; - - for(i=0; i < K; ++i) - polyeta_unpack(&s2->vec[i], sk + i*POLYETA_PACKEDBYTES); - sk += K*POLYETA_PACKEDBYTES; - - for(i=0; i < K; ++i) - polyt0_unpack(&t0->vec[i], sk + i*POLYT0_PACKEDBYTES); -} - -/************************************************* -* Name: pack_sig -* -* Description: Bit-pack signature sig = (c, z, h). -* -* Arguments: - uint8_t sig[]: output byte array -* - const uint8_t *c: pointer to challenge hash length SEEDBYTES -* - const polyvecl *z: pointer to vector z -* - const polyveck *h: pointer to hint vector h -**************************************************/ -void pack_sig(uint8_t sig[CRYPTO_BYTES], - const uint8_t c[CTILDEBYTES], - const polyvecl *z, - const polyveck *h) -{ - unsigned int i, j, k; - - for(i=0; i < CTILDEBYTES; ++i) - sig[i] = c[i]; - sig += CTILDEBYTES; - - for(i = 0; i < L; ++i) - polyz_pack(sig + i*POLYZ_PACKEDBYTES, &z->vec[i]); - sig += L*POLYZ_PACKEDBYTES; - - /* Encode h */ - for(i = 0; i < OMEGA + K; ++i) - sig[i] = 0; - - k = 0; - for(i = 0; i < K; ++i) { - for(j = 0; j < N; ++j) - if(h->vec[i].coeffs[j] != 0) - sig[k++] = j; - - sig[OMEGA + i] = k; - } -} - -/************************************************* -* Name: unpack_sig -* -* Description: Unpack signature sig = (c, z, h). -* -* Arguments: - uint8_t *c: pointer to output challenge hash -* - polyvecl *z: pointer to output vector z -* - polyveck *h: pointer to output hint vector h -* - const uint8_t sig[]: byte array containing -* bit-packed signature -* -* Returns 1 in case of malformed signature; otherwise 0. -**************************************************/ -int unpack_sig(uint8_t c[CTILDEBYTES], - polyvecl *z, - polyveck *h, - const uint8_t sig[CRYPTO_BYTES]) -{ - unsigned int i, j, k; - - for(i = 0; i < CTILDEBYTES; ++i) - c[i] = sig[i]; - sig += CTILDEBYTES; - - for(i = 0; i < L; ++i) - polyz_unpack(&z->vec[i], sig + i*POLYZ_PACKEDBYTES); - sig += L*POLYZ_PACKEDBYTES; - - /* Decode h */ - k = 0; - for(i = 0; i < K; ++i) { - for(j = 0; j < N; ++j) - h->vec[i].coeffs[j] = 0; - - if(sig[OMEGA + i] < k || sig[OMEGA + i] > OMEGA) - return 1; - - for(j = k; j < sig[OMEGA + i]; ++j) { - /* Coefficients are ordered for strong unforgeability */ - if(j > k && sig[j] <= sig[j-1]) return 1; - h->vec[i].coeffs[sig[j]] = 1; - } - - k = sig[OMEGA + i]; - } - - /* Extra indices are zero for strong unforgeability */ - for(j = k; j < OMEGA; ++j) - if(sig[j]) - return 1; - - return 0; -} diff --git a/dilithium/ref/packing.h b/dilithium/ref/packing.h deleted file mode 100644 index 8e47728..0000000 --- a/dilithium/ref/packing.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PACKING_H -#define PACKING_H - -#include -#include "params.h" -#include "polyvec.h" - -#define pack_pk DILITHIUM_NAMESPACE(pack_pk) -void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], const uint8_t rho[SEEDBYTES], const polyveck *t1); - -#define pack_sk DILITHIUM_NAMESPACE(pack_sk) -void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], - const uint8_t rho[SEEDBYTES], - const uint8_t tr[TRBYTES], - const uint8_t key[SEEDBYTES], - const polyveck *t0, - const polyvecl *s1, - const polyveck *s2); - -#define pack_sig DILITHIUM_NAMESPACE(pack_sig) -void pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c[CTILDEBYTES], const polyvecl *z, const polyveck *h); - -#define unpack_pk DILITHIUM_NAMESPACE(unpack_pk) -void unpack_pk(uint8_t rho[SEEDBYTES], polyveck *t1, const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); - -#define unpack_sk DILITHIUM_NAMESPACE(unpack_sk) -void unpack_sk(uint8_t rho[SEEDBYTES], - uint8_t tr[TRBYTES], - uint8_t key[SEEDBYTES], - polyveck *t0, - polyvecl *s1, - polyveck *s2, - const uint8_t sk[CRYPTO_SECRETKEYBYTES]); - -#define unpack_sig DILITHIUM_NAMESPACE(unpack_sig) -int unpack_sig(uint8_t c[CTILDEBYTES], polyvecl *z, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); - -#endif diff --git a/dilithium/ref/params.h b/dilithium/ref/params.h deleted file mode 100644 index 1e8a7b5..0000000 --- a/dilithium/ref/params.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef PARAMS_H -#define PARAMS_H - -#include "config.h" - -#define SEEDBYTES 32 -#define CRHBYTES 64 -#define TRBYTES 64 -#define RNDBYTES 32 -#define N 256 -#define Q 8380417 -#define D 13 -#define ROOT_OF_UNITY 1753 - -#if DILITHIUM_MODE == 2 -#define K 4 -#define L 4 -#define ETA 2 -#define TAU 39 -#define BETA 78 -#define GAMMA1 (1 << 17) -#define GAMMA2 ((Q-1)/88) -#define OMEGA 80 -#define CTILDEBYTES 32 - -#elif DILITHIUM_MODE == 3 -#define K 6 -#define L 5 -#define ETA 4 -#define TAU 49 -#define BETA 196 -#define GAMMA1 (1 << 19) -#define GAMMA2 ((Q-1)/32) -#define OMEGA 55 -#define CTILDEBYTES 48 - -#elif DILITHIUM_MODE == 5 -#define K 8 -#define L 7 -#define ETA 2 -#define TAU 60 -#define BETA 120 -#define GAMMA1 (1 << 19) -#define GAMMA2 ((Q-1)/32) -#define OMEGA 75 -#define CTILDEBYTES 64 - -#endif - -#define POLYT1_PACKEDBYTES 320 -#define POLYT0_PACKEDBYTES 416 -#define POLYVECH_PACKEDBYTES (OMEGA + K) - -#if GAMMA1 == (1 << 17) -#define POLYZ_PACKEDBYTES 576 -#elif GAMMA1 == (1 << 19) -#define POLYZ_PACKEDBYTES 640 -#endif - -#if GAMMA2 == (Q-1)/88 -#define POLYW1_PACKEDBYTES 192 -#elif GAMMA2 == (Q-1)/32 -#define POLYW1_PACKEDBYTES 128 -#endif - -#if ETA == 2 -#define POLYETA_PACKEDBYTES 96 -#elif ETA == 4 -#define POLYETA_PACKEDBYTES 128 -#endif - -#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K*POLYT1_PACKEDBYTES) -#define CRYPTO_SECRETKEYBYTES (2*SEEDBYTES \ - + TRBYTES \ - + L*POLYETA_PACKEDBYTES \ - + K*POLYETA_PACKEDBYTES \ - + K*POLYT0_PACKEDBYTES) -#define CRYPTO_BYTES (CTILDEBYTES + L*POLYZ_PACKEDBYTES + POLYVECH_PACKEDBYTES) - -#endif diff --git a/dilithium/ref/poly.c b/dilithium/ref/poly.c deleted file mode 100644 index 0db4f42..0000000 --- a/dilithium/ref/poly.c +++ /dev/null @@ -1,907 +0,0 @@ -#include -#include "params.h" -#include "poly.h" -#include "ntt.h" -#include "reduce.h" -#include "rounding.h" -#include "symmetric.h" - -#ifdef DBENCH -#include "test/cpucycles.h" -extern const uint64_t timing_overhead; -extern uint64_t *tred, *tadd, *tmul, *tround, *tsample, *tpack; -#define DBENCH_START() uint64_t time = cpucycles() -#define DBENCH_STOP(t) t += cpucycles() - time - timing_overhead -#else -#define DBENCH_START() -#define DBENCH_STOP(t) -#endif - -/************************************************* -* Name: poly_reduce -* -* Description: Inplace reduction of all coefficients of polynomial to -* representative in [-6283008,6283008]. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_reduce(poly *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - a->coeffs[i] = reduce32(a->coeffs[i]); - - DBENCH_STOP(*tred); -} - -/************************************************* -* Name: poly_caddq -* -* Description: For all coefficients of in/out polynomial add Q if -* coefficient is negative. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_caddq(poly *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - a->coeffs[i] = caddq(a->coeffs[i]); - - DBENCH_STOP(*tred); -} - -/************************************************* -* Name: poly_add -* -* Description: Add polynomials. No modular reduction is performed. -* -* Arguments: - poly *c: pointer to output polynomial -* - const poly *a: pointer to first summand -* - const poly *b: pointer to second summand -**************************************************/ -void poly_add(poly *c, const poly *a, const poly *b) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; - - DBENCH_STOP(*tadd); -} - -/************************************************* -* Name: poly_sub -* -* Description: Subtract polynomials. No modular reduction is -* performed. -* -* Arguments: - poly *c: pointer to output polynomial -* - const poly *a: pointer to first input polynomial -* - const poly *b: pointer to second input polynomial to be -* subtraced from first input polynomial -**************************************************/ -void poly_sub(poly *c, const poly *a, const poly *b) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; - - DBENCH_STOP(*tadd); -} - -/************************************************* -* Name: poly_shiftl -* -* Description: Multiply polynomial by 2^D without modular reduction. Assumes -* input coefficients to be less than 2^{31-D} in absolute value. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_shiftl(poly *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - a->coeffs[i] <<= D; - - DBENCH_STOP(*tmul); -} - -/************************************************* -* Name: poly_ntt -* -* Description: Inplace forward NTT. Coefficients can grow by -* 8*Q in absolute value. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_ntt(poly *a) { - DBENCH_START(); - - ntt(a->coeffs); - - DBENCH_STOP(*tmul); -} - -/************************************************* -* Name: poly_invntt_tomont -* -* Description: Inplace inverse NTT and multiplication by 2^{32}. -* Input coefficients need to be less than Q in absolute -* value and output coefficients are again bounded by Q. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_invntt_tomont(poly *a) { - DBENCH_START(); - - invntt_tomont(a->coeffs); - - DBENCH_STOP(*tmul); -} - -/************************************************* -* Name: poly_pointwise_montgomery -* -* Description: Pointwise multiplication of polynomials in NTT domain -* representation and multiplication of resulting polynomial -* by 2^{-32}. -* -* Arguments: - poly *c: pointer to output polynomial -* - const poly *a: pointer to first input polynomial -* - const poly *b: pointer to second input polynomial -**************************************************/ -void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); - - DBENCH_STOP(*tmul); -} - -/************************************************* -* Name: poly_power2round -* -* Description: For all coefficients c of the input polynomial, -* compute c0, c1 such that c mod Q = c1*2^D + c0 -* with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be -* standard representatives. -* -* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 -* - poly *a0: pointer to output polynomial with coefficients c0 -* - const poly *a: pointer to input polynomial -**************************************************/ -void poly_power2round(poly *a1, poly *a0, const poly *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - a1->coeffs[i] = power2round(&a0->coeffs[i], a->coeffs[i]); - - DBENCH_STOP(*tround); -} - -/************************************************* -* Name: poly_decompose -* -* Description: For all coefficients c of the input polynomial, -* compute high and low bits c0, c1 such c mod Q = c1*ALPHA + c0 -* with -ALPHA/2 < c0 <= ALPHA/2 except c1 = (Q-1)/ALPHA where we -* set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0. -* Assumes coefficients to be standard representatives. -* -* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 -* - poly *a0: pointer to output polynomial with coefficients c0 -* - const poly *a: pointer to input polynomial -**************************************************/ -void poly_decompose(poly *a1, poly *a0, const poly *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - a1->coeffs[i] = decompose(&a0->coeffs[i], a->coeffs[i]); - - DBENCH_STOP(*tround); -} - -/************************************************* -* Name: poly_make_hint -* -* Description: Compute hint polynomial. The coefficients of which indicate -* whether the low bits of the corresponding coefficient of -* the input polynomial overflow into the high bits. -* -* Arguments: - poly *h: pointer to output hint polynomial -* - const poly *a0: pointer to low part of input polynomial -* - const poly *a1: pointer to high part of input polynomial -* -* Returns number of 1 bits. -**************************************************/ -unsigned int poly_make_hint(poly *h, const poly *a0, const poly *a1) { - unsigned int i, s = 0; - DBENCH_START(); - - for(i = 0; i < N; ++i) { - h->coeffs[i] = make_hint(a0->coeffs[i], a1->coeffs[i]); - s += h->coeffs[i]; - } - - DBENCH_STOP(*tround); - return s; -} - -/************************************************* -* Name: poly_use_hint -* -* Description: Use hint polynomial to correct the high bits of a polynomial. -* -* Arguments: - poly *b: pointer to output polynomial with corrected high bits -* - const poly *a: pointer to input polynomial -* - const poly *h: pointer to input hint polynomial -**************************************************/ -void poly_use_hint(poly *b, const poly *a, const poly *h) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - b->coeffs[i] = use_hint(a->coeffs[i], h->coeffs[i]); - - DBENCH_STOP(*tround); -} - -/************************************************* -* Name: poly_chknorm -* -* Description: Check infinity norm of polynomial against given bound. -* Assumes input coefficients were reduced by reduce32(). -* -* Arguments: - const poly *a: pointer to polynomial -* - int32_t B: norm bound -* -* Returns 0 if norm is strictly smaller than B <= (Q-1)/8 and 1 otherwise. -**************************************************/ -int poly_chknorm(const poly *a, int32_t B) { - unsigned int i; - int32_t t; - DBENCH_START(); - - if(B > (Q-1)/8) - return 1; - - /* It is ok to leak which coefficient violates the bound since - the probability for each coefficient is independent of secret - data but we must not leak the sign of the centralized representative. */ - for(i = 0; i < N; ++i) { - /* Absolute value */ - t = a->coeffs[i] >> 31; - t = a->coeffs[i] - (t & 2*a->coeffs[i]); - - if(t >= B) { - DBENCH_STOP(*tsample); - return 1; - } - } - - DBENCH_STOP(*tsample); - return 0; -} - -/************************************************* -* Name: rej_uniform -* -* Description: Sample uniformly random coefficients in [0, Q-1] by -* performing rejection sampling on array of random bytes. -* -* Arguments: - int32_t *a: pointer to output array (allocated) -* - unsigned int len: number of coefficients to be sampled -* - const uint8_t *buf: array of random bytes -* - unsigned int buflen: length of array of random bytes -* -* Returns number of sampled coefficients. Can be smaller than len if not enough -* random bytes were given. -**************************************************/ -static unsigned int rej_uniform(int32_t *a, - unsigned int len, - const uint8_t *buf, - unsigned int buflen) -{ - unsigned int ctr, pos; - uint32_t t; - DBENCH_START(); - - ctr = pos = 0; - while(ctr < len && pos + 3 <= buflen) { - t = buf[pos++]; - t |= (uint32_t)buf[pos++] << 8; - t |= (uint32_t)buf[pos++] << 16; - t &= 0x7FFFFF; - - if(t < Q) - a[ctr++] = t; - } - - DBENCH_STOP(*tsample); - return ctr; -} - -/************************************************* -* Name: poly_uniform -* -* Description: Sample polynomial with uniformly random coefficients -* in [0,Q-1] by performing rejection sampling on the -* output stream of SHAKE128(seed|nonce) -* -* Arguments: - poly *a: pointer to output polynomial -* - const uint8_t seed[]: byte array with seed of length SEEDBYTES -* - uint16_t nonce: 2-byte nonce -**************************************************/ -#define POLY_UNIFORM_NBLOCKS ((768 + STREAM128_BLOCKBYTES - 1)/STREAM128_BLOCKBYTES) -void poly_uniform(poly *a, - const uint8_t seed[SEEDBYTES], - uint16_t nonce) -{ - unsigned int i, ctr, off; - unsigned int buflen = POLY_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES; - uint8_t buf[POLY_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES + 2]; - stream128_state state; - - stream128_init(&state, seed, nonce); - stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); - - ctr = rej_uniform(a->coeffs, N, buf, buflen); - - while(ctr < N) { - off = buflen % 3; - for(i = 0; i < off; ++i) - buf[i] = buf[buflen - off + i]; - - stream128_squeezeblocks(buf + off, 1, &state); - buflen = STREAM128_BLOCKBYTES + off; - ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen); - } -} - -/************************************************* -* Name: rej_eta -* -* Description: Sample uniformly random coefficients in [-ETA, ETA] by -* performing rejection sampling on array of random bytes. -* -* Arguments: - int32_t *a: pointer to output array (allocated) -* - unsigned int len: number of coefficients to be sampled -* - const uint8_t *buf: array of random bytes -* - unsigned int buflen: length of array of random bytes -* -* Returns number of sampled coefficients. Can be smaller than len if not enough -* random bytes were given. -**************************************************/ -static unsigned int rej_eta(int32_t *a, - unsigned int len, - const uint8_t *buf, - unsigned int buflen) -{ - unsigned int ctr, pos; - uint32_t t0, t1; - DBENCH_START(); - - ctr = pos = 0; - while(ctr < len && pos < buflen) { - t0 = buf[pos] & 0x0F; - t1 = buf[pos++] >> 4; - -#if ETA == 2 - if(t0 < 15) { - t0 = t0 - (205*t0 >> 10)*5; - a[ctr++] = 2 - t0; - } - if(t1 < 15 && ctr < len) { - t1 = t1 - (205*t1 >> 10)*5; - a[ctr++] = 2 - t1; - } -#elif ETA == 4 - if(t0 < 9) - a[ctr++] = 4 - t0; - if(t1 < 9 && ctr < len) - a[ctr++] = 4 - t1; -#endif - } - - DBENCH_STOP(*tsample); - return ctr; -} - -/************************************************* -* Name: poly_uniform_eta -* -* Description: Sample polynomial with uniformly random coefficients -* in [-ETA,ETA] by performing rejection sampling on the -* output stream from SHAKE256(seed|nonce) -* -* Arguments: - poly *a: pointer to output polynomial -* - const uint8_t seed[]: byte array with seed of length CRHBYTES -* - uint16_t nonce: 2-byte nonce -**************************************************/ -#if ETA == 2 -#define POLY_UNIFORM_ETA_NBLOCKS ((136 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) -#elif ETA == 4 -#define POLY_UNIFORM_ETA_NBLOCKS ((227 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) -#endif -void poly_uniform_eta(poly *a, - const uint8_t seed[CRHBYTES], - uint16_t nonce) -{ - unsigned int ctr; - unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS*STREAM256_BLOCKBYTES; - uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS*STREAM256_BLOCKBYTES]; - stream256_state state; - - stream256_init(&state, seed, nonce); - stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state); - - ctr = rej_eta(a->coeffs, N, buf, buflen); - - while(ctr < N) { - stream256_squeezeblocks(buf, 1, &state); - ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES); - } -} - -/************************************************* -* Name: poly_uniform_gamma1m1 -* -* Description: Sample polynomial with uniformly random coefficients -* in [-(GAMMA1 - 1), GAMMA1] by unpacking output stream -* of SHAKE256(seed|nonce) -* -* Arguments: - poly *a: pointer to output polynomial -* - const uint8_t seed[]: byte array with seed of length CRHBYTES -* - uint16_t nonce: 16-bit nonce -**************************************************/ -#define POLY_UNIFORM_GAMMA1_NBLOCKS ((POLYZ_PACKEDBYTES + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) -void poly_uniform_gamma1(poly *a, - const uint8_t seed[CRHBYTES], - uint16_t nonce) -{ - uint8_t buf[POLY_UNIFORM_GAMMA1_NBLOCKS*STREAM256_BLOCKBYTES]; - stream256_state state; - - stream256_init(&state, seed, nonce); - stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1_NBLOCKS, &state); - polyz_unpack(a, buf); -} - -/************************************************* -* Name: challenge -* -* Description: Implementation of H. Samples polynomial with TAU nonzero -* coefficients in {-1,1} using the output stream of -* SHAKE256(seed). -* -* Arguments: - poly *c: pointer to output polynomial -* - const uint8_t mu[]: byte array containing seed of length CTILDEBYTES -**************************************************/ -void poly_challenge(poly *c, const uint8_t seed[CTILDEBYTES]) { - unsigned int i, b, pos; - uint64_t signs; - uint8_t buf[SHAKE256_RATE]; - keccak_state state; - - shake256_init(&state); - shake256_absorb(&state, seed, CTILDEBYTES); - shake256_finalize(&state); - shake256_squeezeblocks(buf, 1, &state); - - signs = 0; - for(i = 0; i < 8; ++i) - signs |= (uint64_t)buf[i] << 8*i; - pos = 8; - - for(i = 0; i < N; ++i) - c->coeffs[i] = 0; - for(i = N-TAU; i < N; ++i) { - do { - if(pos >= SHAKE256_RATE) { - shake256_squeezeblocks(buf, 1, &state); - pos = 0; - } - - b = buf[pos++]; - } while(b > i); - - c->coeffs[i] = c->coeffs[b]; - c->coeffs[b] = 1 - 2*(signs & 1); - signs >>= 1; - } -} - -/************************************************* -* Name: polyeta_pack -* -* Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYETA_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyeta_pack(uint8_t *r, const poly *a) { - unsigned int i; - uint8_t t[8]; - DBENCH_START(); - -#if ETA == 2 - for(i = 0; i < N/8; ++i) { - t[0] = ETA - a->coeffs[8*i+0]; - t[1] = ETA - a->coeffs[8*i+1]; - t[2] = ETA - a->coeffs[8*i+2]; - t[3] = ETA - a->coeffs[8*i+3]; - t[4] = ETA - a->coeffs[8*i+4]; - t[5] = ETA - a->coeffs[8*i+5]; - t[6] = ETA - a->coeffs[8*i+6]; - t[7] = ETA - a->coeffs[8*i+7]; - - r[3*i+0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); - r[3*i+1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); - r[3*i+2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); - } -#elif ETA == 4 - for(i = 0; i < N/2; ++i) { - t[0] = ETA - a->coeffs[2*i+0]; - t[1] = ETA - a->coeffs[2*i+1]; - r[i] = t[0] | (t[1] << 4); - } -#endif - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyeta_unpack -* -* Description: Unpack polynomial with coefficients in [-ETA,ETA]. -* -* Arguments: - poly *r: pointer to output polynomial -* - const uint8_t *a: byte array with bit-packed polynomial -**************************************************/ -void polyeta_unpack(poly *r, const uint8_t *a) { - unsigned int i; - DBENCH_START(); - -#if ETA == 2 - for(i = 0; i < N/8; ++i) { - r->coeffs[8*i+0] = (a[3*i+0] >> 0) & 7; - r->coeffs[8*i+1] = (a[3*i+0] >> 3) & 7; - r->coeffs[8*i+2] = ((a[3*i+0] >> 6) | (a[3*i+1] << 2)) & 7; - r->coeffs[8*i+3] = (a[3*i+1] >> 1) & 7; - r->coeffs[8*i+4] = (a[3*i+1] >> 4) & 7; - r->coeffs[8*i+5] = ((a[3*i+1] >> 7) | (a[3*i+2] << 1)) & 7; - r->coeffs[8*i+6] = (a[3*i+2] >> 2) & 7; - r->coeffs[8*i+7] = (a[3*i+2] >> 5) & 7; - - r->coeffs[8*i+0] = ETA - r->coeffs[8*i+0]; - r->coeffs[8*i+1] = ETA - r->coeffs[8*i+1]; - r->coeffs[8*i+2] = ETA - r->coeffs[8*i+2]; - r->coeffs[8*i+3] = ETA - r->coeffs[8*i+3]; - r->coeffs[8*i+4] = ETA - r->coeffs[8*i+4]; - r->coeffs[8*i+5] = ETA - r->coeffs[8*i+5]; - r->coeffs[8*i+6] = ETA - r->coeffs[8*i+6]; - r->coeffs[8*i+7] = ETA - r->coeffs[8*i+7]; - } -#elif ETA == 4 - for(i = 0; i < N/2; ++i) { - r->coeffs[2*i+0] = a[i] & 0x0F; - r->coeffs[2*i+1] = a[i] >> 4; - r->coeffs[2*i+0] = ETA - r->coeffs[2*i+0]; - r->coeffs[2*i+1] = ETA - r->coeffs[2*i+1]; - } -#endif - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyt1_pack -* -* Description: Bit-pack polynomial t1 with coefficients fitting in 10 bits. -* Input coefficients are assumed to be standard representatives. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYT1_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyt1_pack(uint8_t *r, const poly *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N/4; ++i) { - r[5*i+0] = (a->coeffs[4*i+0] >> 0); - r[5*i+1] = (a->coeffs[4*i+0] >> 8) | (a->coeffs[4*i+1] << 2); - r[5*i+2] = (a->coeffs[4*i+1] >> 6) | (a->coeffs[4*i+2] << 4); - r[5*i+3] = (a->coeffs[4*i+2] >> 4) | (a->coeffs[4*i+3] << 6); - r[5*i+4] = (a->coeffs[4*i+3] >> 2); - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyt1_unpack -* -* Description: Unpack polynomial t1 with 10-bit coefficients. -* Output coefficients are standard representatives. -* -* Arguments: - poly *r: pointer to output polynomial -* - const uint8_t *a: byte array with bit-packed polynomial -**************************************************/ -void polyt1_unpack(poly *r, const uint8_t *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N/4; ++i) { - r->coeffs[4*i+0] = ((a[5*i+0] >> 0) | ((uint32_t)a[5*i+1] << 8)) & 0x3FF; - r->coeffs[4*i+1] = ((a[5*i+1] >> 2) | ((uint32_t)a[5*i+2] << 6)) & 0x3FF; - r->coeffs[4*i+2] = ((a[5*i+2] >> 4) | ((uint32_t)a[5*i+3] << 4)) & 0x3FF; - r->coeffs[4*i+3] = ((a[5*i+3] >> 6) | ((uint32_t)a[5*i+4] << 2)) & 0x3FF; - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyt0_pack -* -* Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYT0_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyt0_pack(uint8_t *r, const poly *a) { - unsigned int i; - uint32_t t[8]; - DBENCH_START(); - - for(i = 0; i < N/8; ++i) { - t[0] = (1 << (D-1)) - a->coeffs[8*i+0]; - t[1] = (1 << (D-1)) - a->coeffs[8*i+1]; - t[2] = (1 << (D-1)) - a->coeffs[8*i+2]; - t[3] = (1 << (D-1)) - a->coeffs[8*i+3]; - t[4] = (1 << (D-1)) - a->coeffs[8*i+4]; - t[5] = (1 << (D-1)) - a->coeffs[8*i+5]; - t[6] = (1 << (D-1)) - a->coeffs[8*i+6]; - t[7] = (1 << (D-1)) - a->coeffs[8*i+7]; - - r[13*i+ 0] = t[0]; - r[13*i+ 1] = t[0] >> 8; - r[13*i+ 1] |= t[1] << 5; - r[13*i+ 2] = t[1] >> 3; - r[13*i+ 3] = t[1] >> 11; - r[13*i+ 3] |= t[2] << 2; - r[13*i+ 4] = t[2] >> 6; - r[13*i+ 4] |= t[3] << 7; - r[13*i+ 5] = t[3] >> 1; - r[13*i+ 6] = t[3] >> 9; - r[13*i+ 6] |= t[4] << 4; - r[13*i+ 7] = t[4] >> 4; - r[13*i+ 8] = t[4] >> 12; - r[13*i+ 8] |= t[5] << 1; - r[13*i+ 9] = t[5] >> 7; - r[13*i+ 9] |= t[6] << 6; - r[13*i+10] = t[6] >> 2; - r[13*i+11] = t[6] >> 10; - r[13*i+11] |= t[7] << 3; - r[13*i+12] = t[7] >> 5; - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyt0_unpack -* -* Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. -* -* Arguments: - poly *r: pointer to output polynomial -* - const uint8_t *a: byte array with bit-packed polynomial -**************************************************/ -void polyt0_unpack(poly *r, const uint8_t *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N/8; ++i) { - r->coeffs[8*i+0] = a[13*i+0]; - r->coeffs[8*i+0] |= (uint32_t)a[13*i+1] << 8; - r->coeffs[8*i+0] &= 0x1FFF; - - r->coeffs[8*i+1] = a[13*i+1] >> 5; - r->coeffs[8*i+1] |= (uint32_t)a[13*i+2] << 3; - r->coeffs[8*i+1] |= (uint32_t)a[13*i+3] << 11; - r->coeffs[8*i+1] &= 0x1FFF; - - r->coeffs[8*i+2] = a[13*i+3] >> 2; - r->coeffs[8*i+2] |= (uint32_t)a[13*i+4] << 6; - r->coeffs[8*i+2] &= 0x1FFF; - - r->coeffs[8*i+3] = a[13*i+4] >> 7; - r->coeffs[8*i+3] |= (uint32_t)a[13*i+5] << 1; - r->coeffs[8*i+3] |= (uint32_t)a[13*i+6] << 9; - r->coeffs[8*i+3] &= 0x1FFF; - - r->coeffs[8*i+4] = a[13*i+6] >> 4; - r->coeffs[8*i+4] |= (uint32_t)a[13*i+7] << 4; - r->coeffs[8*i+4] |= (uint32_t)a[13*i+8] << 12; - r->coeffs[8*i+4] &= 0x1FFF; - - r->coeffs[8*i+5] = a[13*i+8] >> 1; - r->coeffs[8*i+5] |= (uint32_t)a[13*i+9] << 7; - r->coeffs[8*i+5] &= 0x1FFF; - - r->coeffs[8*i+6] = a[13*i+9] >> 6; - r->coeffs[8*i+6] |= (uint32_t)a[13*i+10] << 2; - r->coeffs[8*i+6] |= (uint32_t)a[13*i+11] << 10; - r->coeffs[8*i+6] &= 0x1FFF; - - r->coeffs[8*i+7] = a[13*i+11] >> 3; - r->coeffs[8*i+7] |= (uint32_t)a[13*i+12] << 5; - r->coeffs[8*i+7] &= 0x1FFF; - - r->coeffs[8*i+0] = (1 << (D-1)) - r->coeffs[8*i+0]; - r->coeffs[8*i+1] = (1 << (D-1)) - r->coeffs[8*i+1]; - r->coeffs[8*i+2] = (1 << (D-1)) - r->coeffs[8*i+2]; - r->coeffs[8*i+3] = (1 << (D-1)) - r->coeffs[8*i+3]; - r->coeffs[8*i+4] = (1 << (D-1)) - r->coeffs[8*i+4]; - r->coeffs[8*i+5] = (1 << (D-1)) - r->coeffs[8*i+5]; - r->coeffs[8*i+6] = (1 << (D-1)) - r->coeffs[8*i+6]; - r->coeffs[8*i+7] = (1 << (D-1)) - r->coeffs[8*i+7]; - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyz_pack -* -* Description: Bit-pack polynomial with coefficients -* in [-(GAMMA1 - 1), GAMMA1]. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYZ_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyz_pack(uint8_t *r, const poly *a) { - unsigned int i; - uint32_t t[4]; - DBENCH_START(); - -#if GAMMA1 == (1 << 17) - for(i = 0; i < N/4; ++i) { - t[0] = GAMMA1 - a->coeffs[4*i+0]; - t[1] = GAMMA1 - a->coeffs[4*i+1]; - t[2] = GAMMA1 - a->coeffs[4*i+2]; - t[3] = GAMMA1 - a->coeffs[4*i+3]; - - r[9*i+0] = t[0]; - r[9*i+1] = t[0] >> 8; - r[9*i+2] = t[0] >> 16; - r[9*i+2] |= t[1] << 2; - r[9*i+3] = t[1] >> 6; - r[9*i+4] = t[1] >> 14; - r[9*i+4] |= t[2] << 4; - r[9*i+5] = t[2] >> 4; - r[9*i+6] = t[2] >> 12; - r[9*i+6] |= t[3] << 6; - r[9*i+7] = t[3] >> 2; - r[9*i+8] = t[3] >> 10; - } -#elif GAMMA1 == (1 << 19) - for(i = 0; i < N/2; ++i) { - t[0] = GAMMA1 - a->coeffs[2*i+0]; - t[1] = GAMMA1 - a->coeffs[2*i+1]; - - r[5*i+0] = t[0]; - r[5*i+1] = t[0] >> 8; - r[5*i+2] = t[0] >> 16; - r[5*i+2] |= t[1] << 4; - r[5*i+3] = t[1] >> 4; - r[5*i+4] = t[1] >> 12; - } -#endif - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyz_unpack -* -* Description: Unpack polynomial z with coefficients -* in [-(GAMMA1 - 1), GAMMA1]. -* -* Arguments: - poly *r: pointer to output polynomial -* - const uint8_t *a: byte array with bit-packed polynomial -**************************************************/ -void polyz_unpack(poly *r, const uint8_t *a) { - unsigned int i; - DBENCH_START(); - -#if GAMMA1 == (1 << 17) - for(i = 0; i < N/4; ++i) { - r->coeffs[4*i+0] = a[9*i+0]; - r->coeffs[4*i+0] |= (uint32_t)a[9*i+1] << 8; - r->coeffs[4*i+0] |= (uint32_t)a[9*i+2] << 16; - r->coeffs[4*i+0] &= 0x3FFFF; - - r->coeffs[4*i+1] = a[9*i+2] >> 2; - r->coeffs[4*i+1] |= (uint32_t)a[9*i+3] << 6; - r->coeffs[4*i+1] |= (uint32_t)a[9*i+4] << 14; - r->coeffs[4*i+1] &= 0x3FFFF; - - r->coeffs[4*i+2] = a[9*i+4] >> 4; - r->coeffs[4*i+2] |= (uint32_t)a[9*i+5] << 4; - r->coeffs[4*i+2] |= (uint32_t)a[9*i+6] << 12; - r->coeffs[4*i+2] &= 0x3FFFF; - - r->coeffs[4*i+3] = a[9*i+6] >> 6; - r->coeffs[4*i+3] |= (uint32_t)a[9*i+7] << 2; - r->coeffs[4*i+3] |= (uint32_t)a[9*i+8] << 10; - r->coeffs[4*i+3] &= 0x3FFFF; - - r->coeffs[4*i+0] = GAMMA1 - r->coeffs[4*i+0]; - r->coeffs[4*i+1] = GAMMA1 - r->coeffs[4*i+1]; - r->coeffs[4*i+2] = GAMMA1 - r->coeffs[4*i+2]; - r->coeffs[4*i+3] = GAMMA1 - r->coeffs[4*i+3]; - } -#elif GAMMA1 == (1 << 19) - for(i = 0; i < N/2; ++i) { - r->coeffs[2*i+0] = a[5*i+0]; - r->coeffs[2*i+0] |= (uint32_t)a[5*i+1] << 8; - r->coeffs[2*i+0] |= (uint32_t)a[5*i+2] << 16; - r->coeffs[2*i+0] &= 0xFFFFF; - - r->coeffs[2*i+1] = a[5*i+2] >> 4; - r->coeffs[2*i+1] |= (uint32_t)a[5*i+3] << 4; - r->coeffs[2*i+1] |= (uint32_t)a[5*i+4] << 12; - /* r->coeffs[2*i+1] &= 0xFFFFF; */ /* No effect, since we're anyway at 20 bits */ - - r->coeffs[2*i+0] = GAMMA1 - r->coeffs[2*i+0]; - r->coeffs[2*i+1] = GAMMA1 - r->coeffs[2*i+1]; - } -#endif - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyw1_pack -* -* Description: Bit-pack polynomial w1 with coefficients in [0,15] or [0,43]. -* Input coefficients are assumed to be standard representatives. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYW1_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyw1_pack(uint8_t *r, const poly *a) { - unsigned int i; - DBENCH_START(); - -#if GAMMA2 == (Q-1)/88 - for(i = 0; i < N/4; ++i) { - r[3*i+0] = a->coeffs[4*i+0]; - r[3*i+0] |= a->coeffs[4*i+1] << 6; - r[3*i+1] = a->coeffs[4*i+1] >> 2; - r[3*i+1] |= a->coeffs[4*i+2] << 4; - r[3*i+2] = a->coeffs[4*i+2] >> 4; - r[3*i+2] |= a->coeffs[4*i+3] << 2; - } -#elif GAMMA2 == (Q-1)/32 - for(i = 0; i < N/2; ++i) - r[i] = a->coeffs[2*i+0] | (a->coeffs[2*i+1] << 4); -#endif - - DBENCH_STOP(*tpack); -} diff --git a/dilithium/ref/poly.h b/dilithium/ref/poly.h deleted file mode 100644 index 904baa1..0000000 --- a/dilithium/ref/poly.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef POLY_H -#define POLY_H - -#include -#include "params.h" - -typedef struct { - int32_t coeffs[N]; -} poly; - -#define poly_reduce DILITHIUM_NAMESPACE(poly_reduce) -void poly_reduce(poly *a); -#define poly_caddq DILITHIUM_NAMESPACE(poly_caddq) -void poly_caddq(poly *a); - -#define poly_add DILITHIUM_NAMESPACE(poly_add) -void poly_add(poly *c, const poly *a, const poly *b); -#define poly_sub DILITHIUM_NAMESPACE(poly_sub) -void poly_sub(poly *c, const poly *a, const poly *b); -#define poly_shiftl DILITHIUM_NAMESPACE(poly_shiftl) -void poly_shiftl(poly *a); - -#define poly_ntt DILITHIUM_NAMESPACE(poly_ntt) -void poly_ntt(poly *a); -#define poly_invntt_tomont DILITHIUM_NAMESPACE(poly_invntt_tomont) -void poly_invntt_tomont(poly *a); -#define poly_pointwise_montgomery DILITHIUM_NAMESPACE(poly_pointwise_montgomery) -void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); - -#define poly_power2round DILITHIUM_NAMESPACE(poly_power2round) -void poly_power2round(poly *a1, poly *a0, const poly *a); -#define poly_decompose DILITHIUM_NAMESPACE(poly_decompose) -void poly_decompose(poly *a1, poly *a0, const poly *a); -#define poly_make_hint DILITHIUM_NAMESPACE(poly_make_hint) -unsigned int poly_make_hint(poly *h, const poly *a0, const poly *a1); -#define poly_use_hint DILITHIUM_NAMESPACE(poly_use_hint) -void poly_use_hint(poly *b, const poly *a, const poly *h); - -#define poly_chknorm DILITHIUM_NAMESPACE(poly_chknorm) -int poly_chknorm(const poly *a, int32_t B); -#define poly_uniform DILITHIUM_NAMESPACE(poly_uniform) -void poly_uniform(poly *a, - const uint8_t seed[SEEDBYTES], - uint16_t nonce); -#define poly_uniform_eta DILITHIUM_NAMESPACE(poly_uniform_eta) -void poly_uniform_eta(poly *a, - const uint8_t seed[CRHBYTES], - uint16_t nonce); -#define poly_uniform_gamma1 DILITHIUM_NAMESPACE(poly_uniform_gamma1) -void poly_uniform_gamma1(poly *a, - const uint8_t seed[CRHBYTES], - uint16_t nonce); -#define poly_challenge DILITHIUM_NAMESPACE(poly_challenge) -void poly_challenge(poly *c, const uint8_t seed[CTILDEBYTES]); - -#define polyeta_pack DILITHIUM_NAMESPACE(polyeta_pack) -void polyeta_pack(uint8_t *r, const poly *a); -#define polyeta_unpack DILITHIUM_NAMESPACE(polyeta_unpack) -void polyeta_unpack(poly *r, const uint8_t *a); - -#define polyt1_pack DILITHIUM_NAMESPACE(polyt1_pack) -void polyt1_pack(uint8_t *r, const poly *a); -#define polyt1_unpack DILITHIUM_NAMESPACE(polyt1_unpack) -void polyt1_unpack(poly *r, const uint8_t *a); - -#define polyt0_pack DILITHIUM_NAMESPACE(polyt0_pack) -void polyt0_pack(uint8_t *r, const poly *a); -#define polyt0_unpack DILITHIUM_NAMESPACE(polyt0_unpack) -void polyt0_unpack(poly *r, const uint8_t *a); - -#define polyz_pack DILITHIUM_NAMESPACE(polyz_pack) -void polyz_pack(uint8_t *r, const poly *a); -#define polyz_unpack DILITHIUM_NAMESPACE(polyz_unpack) -void polyz_unpack(poly *r, const uint8_t *a); - -#define polyw1_pack DILITHIUM_NAMESPACE(polyw1_pack) -void polyw1_pack(uint8_t *r, const poly *a); - -#endif diff --git a/dilithium/ref/polyvec.c b/dilithium/ref/polyvec.c deleted file mode 100644 index 241f618..0000000 --- a/dilithium/ref/polyvec.c +++ /dev/null @@ -1,389 +0,0 @@ -#include -#include "params.h" -#include "polyvec.h" -#include "poly.h" - -/************************************************* -* Name: expand_mat -* -* Description: Implementation of ExpandA. Generates matrix A with uniformly -* random coefficients a_{i,j} by performing rejection -* sampling on the output stream of SHAKE128(rho|j|i) -* -* Arguments: - polyvecl mat[K]: output matrix -* - const uint8_t rho[]: byte array containing seed rho -**************************************************/ -void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { - unsigned int i, j; - - for(i = 0; i < K; ++i) - for(j = 0; j < L; ++j) - poly_uniform(&mat[i].vec[j], rho, (i << 8) + j); -} - -void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); -} - -/**************************************************************/ -/************ Vectors of polynomials of length L **************/ -/**************************************************************/ - -void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_uniform_eta(&v->vec[i], seed, nonce++); -} - -void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_uniform_gamma1(&v->vec[i], seed, L*nonce + i); -} - -void polyvecl_reduce(polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_reduce(&v->vec[i]); -} - -/************************************************* -* Name: polyvecl_add -* -* Description: Add vectors of polynomials of length L. -* No modular reduction is performed. -* -* Arguments: - polyvecl *w: pointer to output vector -* - const polyvecl *u: pointer to first summand -* - const polyvecl *v: pointer to second summand -**************************************************/ -void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyvecl_ntt -* -* Description: Forward NTT of all polynomials in vector of length L. Output -* coefficients can be up to 16*Q larger than input coefficients. -* -* Arguments: - polyvecl *v: pointer to input/output vector -**************************************************/ -void polyvecl_ntt(polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_ntt(&v->vec[i]); -} - -void polyvecl_invntt_tomont(polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_invntt_tomont(&v->vec[i]); -} - -void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); -} - -/************************************************* -* Name: polyvecl_pointwise_acc_montgomery -* -* Description: Pointwise multiply vectors of polynomials of length L, multiply -* resulting vector by 2^{-32} and add (accumulate) polynomials -* in it. Input/output vectors are in NTT domain representation. -* -* Arguments: - poly *w: output polynomial -* - const polyvecl *u: pointer to first input vector -* - const polyvecl *v: pointer to second input vector -**************************************************/ -void polyvecl_pointwise_acc_montgomery(poly *w, - const polyvecl *u, - const polyvecl *v) -{ - unsigned int i; - poly t; - - poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); - for(i = 1; i < L; ++i) { - poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); - poly_add(w, w, &t); - } -} - -/************************************************* -* Name: polyvecl_chknorm -* -* Description: Check infinity norm of polynomials in vector of length L. -* Assumes input polyvecl to be reduced by polyvecl_reduce(). -* -* Arguments: - const polyvecl *v: pointer to vector -* - int32_t B: norm bound -* -* Returns 0 if norm of all polynomials is strictly smaller than B <= (Q-1)/8 -* and 1 otherwise. -**************************************************/ -int polyvecl_chknorm(const polyvecl *v, int32_t bound) { - unsigned int i; - - for(i = 0; i < L; ++i) - if(poly_chknorm(&v->vec[i], bound)) - return 1; - - return 0; -} - -/**************************************************************/ -/************ Vectors of polynomials of length K **************/ -/**************************************************************/ - -void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_uniform_eta(&v->vec[i], seed, nonce++); -} - -/************************************************* -* Name: polyveck_reduce -* -* Description: Reduce coefficients of polynomials in vector of length K -* to representatives in [-6283008,6283008]. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_reduce(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_reduce(&v->vec[i]); -} - -/************************************************* -* Name: polyveck_caddq -* -* Description: For all coefficients of polynomials in vector of length K -* add Q if coefficient is negative. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_caddq(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_caddq(&v->vec[i]); -} - -/************************************************* -* Name: polyveck_add -* -* Description: Add vectors of polynomials of length K. -* No modular reduction is performed. -* -* Arguments: - polyveck *w: pointer to output vector -* - const polyveck *u: pointer to first summand -* - const polyveck *v: pointer to second summand -**************************************************/ -void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_sub -* -* Description: Subtract vectors of polynomials of length K. -* No modular reduction is performed. -* -* Arguments: - polyveck *w: pointer to output vector -* - const polyveck *u: pointer to first input vector -* - const polyveck *v: pointer to second input vector to be -* subtracted from first input vector -**************************************************/ -void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_shiftl -* -* Description: Multiply vector of polynomials of Length K by 2^D without modular -* reduction. Assumes input coefficients to be less than 2^{31-D}. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_shiftl(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_shiftl(&v->vec[i]); -} - -/************************************************* -* Name: polyveck_ntt -* -* Description: Forward NTT of all polynomials in vector of length K. Output -* coefficients can be up to 16*Q larger than input coefficients. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_ntt(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_ntt(&v->vec[i]); -} - -/************************************************* -* Name: polyveck_invntt_tomont -* -* Description: Inverse NTT and multiplication by 2^{32} of polynomials -* in vector of length K. Input coefficients need to be less -* than 2*Q. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_invntt_tomont(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_invntt_tomont(&v->vec[i]); -} - -void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); -} - - -/************************************************* -* Name: polyveck_chknorm -* -* Description: Check infinity norm of polynomials in vector of length K. -* Assumes input polyveck to be reduced by polyveck_reduce(). -* -* Arguments: - const polyveck *v: pointer to vector -* - int32_t B: norm bound -* -* Returns 0 if norm of all polynomials are strictly smaller than B <= (Q-1)/8 -* and 1 otherwise. -**************************************************/ -int polyveck_chknorm(const polyveck *v, int32_t bound) { - unsigned int i; - - for(i = 0; i < K; ++i) - if(poly_chknorm(&v->vec[i], bound)) - return 1; - - return 0; -} - -/************************************************* -* Name: polyveck_power2round -* -* Description: For all coefficients a of polynomials in vector of length K, -* compute a0, a1 such that a mod^+ Q = a1*2^D + a0 -* with -2^{D-1} < a0 <= 2^{D-1}. Assumes coefficients to be -* standard representatives. -* -* Arguments: - polyveck *v1: pointer to output vector of polynomials with -* coefficients a1 -* - polyveck *v0: pointer to output vector of polynomials with -* coefficients a0 -* - const polyveck *v: pointer to input vector -**************************************************/ -void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_power2round(&v1->vec[i], &v0->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_decompose -* -* Description: For all coefficients a of polynomials in vector of length K, -* compute high and low bits a0, a1 such a mod^+ Q = a1*ALPHA + a0 -* with -ALPHA/2 < a0 <= ALPHA/2 except a1 = (Q-1)/ALPHA where we -* set a1 = 0 and -ALPHA/2 <= a0 = a mod Q - Q < 0. -* Assumes coefficients to be standard representatives. -* -* Arguments: - polyveck *v1: pointer to output vector of polynomials with -* coefficients a1 -* - polyveck *v0: pointer to output vector of polynomials with -* coefficients a0 -* - const polyveck *v: pointer to input vector -**************************************************/ -void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_decompose(&v1->vec[i], &v0->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_make_hint -* -* Description: Compute hint vector. -* -* Arguments: - polyveck *h: pointer to output vector -* - const polyveck *v0: pointer to low part of input vector -* - const polyveck *v1: pointer to high part of input vector -* -* Returns number of 1 bits. -**************************************************/ -unsigned int polyveck_make_hint(polyveck *h, - const polyveck *v0, - const polyveck *v1) -{ - unsigned int i, s = 0; - - for(i = 0; i < K; ++i) - s += poly_make_hint(&h->vec[i], &v0->vec[i], &v1->vec[i]); - - return s; -} - -/************************************************* -* Name: polyveck_use_hint -* -* Description: Use hint vector to correct the high bits of input vector. -* -* Arguments: - polyveck *w: pointer to output vector of polynomials with -* corrected high bits -* - const polyveck *u: pointer to input vector -* - const polyveck *h: pointer to input hint vector -**************************************************/ -void polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_use_hint(&w->vec[i], &u->vec[i], &h->vec[i]); -} - -void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1) { - unsigned int i; - - for(i = 0; i < K; ++i) - polyw1_pack(&r[i*POLYW1_PACKEDBYTES], &w1->vec[i]); -} diff --git a/dilithium/ref/polyvec.h b/dilithium/ref/polyvec.h deleted file mode 100644 index 615ac52..0000000 --- a/dilithium/ref/polyvec.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef POLYVEC_H -#define POLYVEC_H - -#include -#include "params.h" -#include "poly.h" - -/* Vectors of polynomials of length L */ -typedef struct { - poly vec[L]; -} polyvecl; - -#define polyvecl_uniform_eta DILITHIUM_NAMESPACE(polyvecl_uniform_eta) -void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define polyvecl_uniform_gamma1 DILITHIUM_NAMESPACE(polyvecl_uniform_gamma1) -void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define polyvecl_reduce DILITHIUM_NAMESPACE(polyvecl_reduce) -void polyvecl_reduce(polyvecl *v); - -#define polyvecl_add DILITHIUM_NAMESPACE(polyvecl_add) -void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v); - -#define polyvecl_ntt DILITHIUM_NAMESPACE(polyvecl_ntt) -void polyvecl_ntt(polyvecl *v); -#define polyvecl_invntt_tomont DILITHIUM_NAMESPACE(polyvecl_invntt_tomont) -void polyvecl_invntt_tomont(polyvecl *v); -#define polyvecl_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyvecl_pointwise_poly_montgomery) -void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v); -#define polyvecl_pointwise_acc_montgomery \ - DILITHIUM_NAMESPACE(polyvecl_pointwise_acc_montgomery) -void polyvecl_pointwise_acc_montgomery(poly *w, - const polyvecl *u, - const polyvecl *v); - - -#define polyvecl_chknorm DILITHIUM_NAMESPACE(polyvecl_chknorm) -int polyvecl_chknorm(const polyvecl *v, int32_t B); - - - -/* Vectors of polynomials of length K */ -typedef struct { - poly vec[K]; -} polyveck; - -#define polyveck_uniform_eta DILITHIUM_NAMESPACE(polyveck_uniform_eta) -void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define polyveck_reduce DILITHIUM_NAMESPACE(polyveck_reduce) -void polyveck_reduce(polyveck *v); -#define polyveck_caddq DILITHIUM_NAMESPACE(polyveck_caddq) -void polyveck_caddq(polyveck *v); - -#define polyveck_add DILITHIUM_NAMESPACE(polyveck_add) -void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v); -#define polyveck_sub DILITHIUM_NAMESPACE(polyveck_sub) -void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v); -#define polyveck_shiftl DILITHIUM_NAMESPACE(polyveck_shiftl) -void polyveck_shiftl(polyveck *v); - -#define polyveck_ntt DILITHIUM_NAMESPACE(polyveck_ntt) -void polyveck_ntt(polyveck *v); -#define polyveck_invntt_tomont DILITHIUM_NAMESPACE(polyveck_invntt_tomont) -void polyveck_invntt_tomont(polyveck *v); -#define polyveck_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyveck_pointwise_poly_montgomery) -void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v); - -#define polyveck_chknorm DILITHIUM_NAMESPACE(polyveck_chknorm) -int polyveck_chknorm(const polyveck *v, int32_t B); - -#define polyveck_power2round DILITHIUM_NAMESPACE(polyveck_power2round) -void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v); -#define polyveck_decompose DILITHIUM_NAMESPACE(polyveck_decompose) -void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v); -#define polyveck_make_hint DILITHIUM_NAMESPACE(polyveck_make_hint) -unsigned int polyveck_make_hint(polyveck *h, - const polyveck *v0, - const polyveck *v1); -#define polyveck_use_hint DILITHIUM_NAMESPACE(polyveck_use_hint) -void polyveck_use_hint(polyveck *w, const polyveck *v, const polyveck *h); - -#define polyveck_pack_w1 DILITHIUM_NAMESPACE(polyveck_pack_w1) -void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1); - -#define polyvec_matrix_expand DILITHIUM_NAMESPACE(polyvec_matrix_expand) -void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); - -#define polyvec_matrix_pointwise_montgomery DILITHIUM_NAMESPACE(polyvec_matrix_pointwise_montgomery) -void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v); - -#endif diff --git a/dilithium/ref/precomp.gp b/dilithium/ref/precomp.gp deleted file mode 100644 index 74dbdf8..0000000 --- a/dilithium/ref/precomp.gp +++ /dev/null @@ -1,12 +0,0 @@ -precomp() = { - brv = [128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255]; - - q = 2^23 - 2^13 + 1; - qinv = Mod(1/q,2^32); - mont = Mod(2^32,q); - - z = 0; - for(i = 1, q-1, z = Mod(i,q); if(znorder(z) == 512, break)); - zetas = vector(255, i, centerlift(mont * z^(brv[i]))); - return(zetas); -} diff --git a/dilithium/ref/randombytes.c b/dilithium/ref/randombytes.c deleted file mode 100644 index 7f4b857..0000000 --- a/dilithium/ref/randombytes.c +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include -#include "randombytes.h" - -#ifdef _WIN32 -#include -#include -#else -#include -#include -#ifdef __linux__ -#define _GNU_SOURCE -#include -#include -#else -#include -#endif -#endif - -#ifdef _WIN32 -void randombytes(uint8_t *out, size_t outlen) { - HCRYPTPROV ctx; - size_t len; - - if(!CryptAcquireContext(&ctx, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - abort(); - - while(outlen > 0) { - len = (outlen > 1048576) ? 1048576 : outlen; - if(!CryptGenRandom(ctx, len, (BYTE *)out)) - abort(); - - out += len; - outlen -= len; - } - - if(!CryptReleaseContext(ctx, 0)) - abort(); -} -#elif defined(__linux__) && defined(SYS_getrandom) -void randombytes(uint8_t *out, size_t outlen) { - ssize_t ret; - - while(outlen > 0) { - ret = syscall(SYS_getrandom, out, outlen, 0); - if(ret == -1 && errno == EINTR) - continue; - else if(ret == -1) - abort(); - - out += ret; - outlen -= ret; - } -} -#else -void randombytes(uint8_t *out, size_t outlen) { - static int fd = -1; - ssize_t ret; - - while(fd == -1) { - fd = open("/dev/urandom", O_RDONLY); - if(fd == -1 && errno == EINTR) - continue; - else if(fd == -1) - abort(); - } - - while(outlen > 0) { - ret = read(fd, out, outlen); - if(ret == -1 && errno == EINTR) - continue; - else if(ret == -1) - abort(); - - out += ret; - outlen -= ret; - } -} -#endif diff --git a/dilithium/ref/randombytes.h b/dilithium/ref/randombytes.h deleted file mode 100644 index 619b7f9..0000000 --- a/dilithium/ref/randombytes.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef RANDOMBYTES_H -#define RANDOMBYTES_H - -#include -#include - -void randombytes(uint8_t *out, size_t outlen); - -#endif diff --git a/dilithium/ref/randombytes_custom.c b/dilithium/ref/randombytes_custom.c deleted file mode 100644 index 2e661fc..0000000 --- a/dilithium/ref/randombytes_custom.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include -#include "randombytes.h" - -/* Forward declaration of our custom implementation from utils.c */ -extern void custom_randombytes_impl(uint8_t *out, size_t outlen); - -/* This function is the original randombytes implementation but calls our custom implementation */ -void randombytes(uint8_t *out, size_t outlen) { - custom_randombytes_impl(out, outlen); -} diff --git a/dilithium/ref/reduce.c b/dilithium/ref/reduce.c deleted file mode 100644 index 8479a22..0000000 --- a/dilithium/ref/reduce.c +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include "params.h" -#include "reduce.h" - -/************************************************* -* Name: montgomery_reduce -* -* Description: For finite field element a with -2^{31}Q <= a <= Q*2^31, -* compute r \equiv a*2^{-32} (mod Q) such that -Q < r < Q. -* -* Arguments: - int64_t: finite field element a -* -* Returns r. -**************************************************/ -int32_t montgomery_reduce(int64_t a) { - int32_t t; - - t = (int64_t)(int32_t)a*QINV; - t = (a - (int64_t)t*Q) >> 32; - return t; -} - -/************************************************* -* Name: reduce32 -* -* Description: For finite field element a with a <= 2^{31} - 2^{22} - 1, -* compute r \equiv a (mod Q) such that -6283008 <= r <= 6283008. -* -* Arguments: - int32_t: finite field element a -* -* Returns r. -**************************************************/ -int32_t reduce32(int32_t a) { - int32_t t; - - t = (a + (1 << 22)) >> 23; - t = a - t*Q; - return t; -} - -/************************************************* -* Name: caddq -* -* Description: Add Q if input coefficient is negative. -* -* Arguments: - int32_t: finite field element a -* -* Returns r. -**************************************************/ -int32_t caddq(int32_t a) { - a += (a >> 31) & Q; - return a; -} - -/************************************************* -* Name: freeze -* -* Description: For finite field element a, compute standard -* representative r = a mod^+ Q. -* -* Arguments: - int32_t: finite field element a -* -* Returns r. -**************************************************/ -int32_t freeze(int32_t a) { - a = reduce32(a); - a = caddq(a); - return a; -} diff --git a/dilithium/ref/reduce.h b/dilithium/ref/reduce.h deleted file mode 100644 index 26d9b4e..0000000 --- a/dilithium/ref/reduce.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef REDUCE_H -#define REDUCE_H - -#include -#include "params.h" - -#define MONT -4186625 // 2^32 % Q -#define QINV 58728449 // q^(-1) mod 2^32 - -#define montgomery_reduce DILITHIUM_NAMESPACE(montgomery_reduce) -int32_t montgomery_reduce(int64_t a); - -#define reduce32 DILITHIUM_NAMESPACE(reduce32) -int32_t reduce32(int32_t a); - -#define caddq DILITHIUM_NAMESPACE(caddq) -int32_t caddq(int32_t a); - -#define freeze DILITHIUM_NAMESPACE(freeze) -int32_t freeze(int32_t a); - -#endif diff --git a/dilithium/ref/rounding.c b/dilithium/ref/rounding.c deleted file mode 100644 index 889f0a2..0000000 --- a/dilithium/ref/rounding.c +++ /dev/null @@ -1,102 +0,0 @@ -#include -#include "params.h" -#include "rounding.h" - -/************************************************* -* Name: power2round -* -* Description: For finite field element a, compute a0, a1 such that -* a mod^+ Q = a1*2^D + a0 with -2^{D-1} < a0 <= 2^{D-1}. -* Assumes a to be standard representative. -* -* Arguments: - int32_t a: input element -* - int32_t *a0: pointer to output element a0 -* -* Returns a1. -**************************************************/ -int32_t power2round(int32_t *a0, int32_t a) { - int32_t a1; - - a1 = (a + (1 << (D-1)) - 1) >> D; - *a0 = a - (a1 << D); - return a1; -} - -/************************************************* -* Name: decompose -* -* Description: For finite field element a, compute high and low bits a0, a1 such -* that a mod^+ Q = a1*ALPHA + a0 with -ALPHA/2 < a0 <= ALPHA/2 except -* if a1 = (Q-1)/ALPHA where we set a1 = 0 and -* -ALPHA/2 <= a0 = a mod^+ Q - Q < 0. Assumes a to be standard -* representative. -* -* Arguments: - int32_t a: input element -* - int32_t *a0: pointer to output element a0 -* -* Returns a1. -**************************************************/ -int32_t decompose(int32_t *a0, int32_t a) { - int32_t a1; - - a1 = (a + 127) >> 7; -#if GAMMA2 == (Q-1)/32 - a1 = (a1*1025 + (1 << 21)) >> 22; - a1 &= 15; -#elif GAMMA2 == (Q-1)/88 - a1 = (a1*11275 + (1 << 23)) >> 24; - a1 ^= ((43 - a1) >> 31) & a1; -#endif - - *a0 = a - a1*2*GAMMA2; - *a0 -= (((Q-1)/2 - *a0) >> 31) & Q; - return a1; -} - -/************************************************* -* Name: make_hint -* -* Description: Compute hint bit indicating whether the low bits of the -* input element overflow into the high bits. -* -* Arguments: - int32_t a0: low bits of input element -* - int32_t a1: high bits of input element -* -* Returns 1 if overflow. -**************************************************/ -unsigned int make_hint(int32_t a0, int32_t a1) { - if(a0 > GAMMA2 || a0 < -GAMMA2 || (a0 == -GAMMA2 && a1 != 0)) - return 1; - - return 0; -} - -/************************************************* -* Name: use_hint -* -* Description: Correct high bits according to hint. -* -* Arguments: - int32_t a: input element -* - unsigned int hint: hint bit -* -* Returns corrected high bits. -**************************************************/ -int32_t use_hint(int32_t a, unsigned int hint) { - int32_t a0, a1; - - a1 = decompose(&a0, a); - if(hint == 0) - return a1; - -#if GAMMA2 == (Q-1)/32 - if(a0 > 0) - return (a1 + 1) & 15; - else - return (a1 - 1) & 15; -#elif GAMMA2 == (Q-1)/88 - if(a0 > 0) - return (a1 == 43) ? 0 : a1 + 1; - else - return (a1 == 0) ? 43 : a1 - 1; -#endif -} diff --git a/dilithium/ref/rounding.h b/dilithium/ref/rounding.h deleted file mode 100644 index b72e8e8..0000000 --- a/dilithium/ref/rounding.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ROUNDING_H -#define ROUNDING_H - -#include -#include "params.h" - -#define power2round DILITHIUM_NAMESPACE(power2round) -int32_t power2round(int32_t *a0, int32_t a); - -#define decompose DILITHIUM_NAMESPACE(decompose) -int32_t decompose(int32_t *a0, int32_t a); - -#define make_hint DILITHIUM_NAMESPACE(make_hint) -unsigned int make_hint(int32_t a0, int32_t a1); - -#define use_hint DILITHIUM_NAMESPACE(use_hint) -int32_t use_hint(int32_t a, unsigned int hint); - -#endif diff --git a/dilithium/ref/sign.c b/dilithium/ref/sign.c deleted file mode 100644 index 7d3f882..0000000 --- a/dilithium/ref/sign.c +++ /dev/null @@ -1,443 +0,0 @@ -#include -#include "params.h" -#include "sign.h" -#include "packing.h" -#include "polyvec.h" -#include "poly.h" -#include "randombytes.h" -#include "symmetric.h" -#include "fips202.h" - -/************************************************* -* Name: crypto_sign_keypair -* -* Description: Generates public and private key. -* -* Arguments: - uint8_t *pk: pointer to output public key (allocated -* array of CRYPTO_PUBLICKEYBYTES bytes) -* - uint8_t *sk: pointer to output private key (allocated -* array of CRYPTO_SECRETKEYBYTES bytes) -* -* Returns 0 (success) -**************************************************/ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seedbuf[2*SEEDBYTES + CRHBYTES]; - uint8_t tr[TRBYTES]; - const uint8_t *rho, *rhoprime, *key; - polyvecl mat[K]; - polyvecl s1, s1hat; - polyveck s2, t1, t0; - - /* Get randomness for rho, rhoprime and key */ - randombytes(seedbuf, SEEDBYTES); - seedbuf[SEEDBYTES+0] = K; - seedbuf[SEEDBYTES+1] = L; - shake256(seedbuf, 2*SEEDBYTES + CRHBYTES, seedbuf, SEEDBYTES+2); - rho = seedbuf; - rhoprime = rho + SEEDBYTES; - key = rhoprime + CRHBYTES; - - /* Expand matrix */ - polyvec_matrix_expand(mat, rho); - - /* Sample short vectors s1 and s2 */ - polyvecl_uniform_eta(&s1, rhoprime, 0); - polyveck_uniform_eta(&s2, rhoprime, L); - - /* Matrix-vector multiplication */ - s1hat = s1; - polyvecl_ntt(&s1hat); - polyvec_matrix_pointwise_montgomery(&t1, mat, &s1hat); - polyveck_reduce(&t1); - polyveck_invntt_tomont(&t1); - - /* Add error vector s2 */ - polyveck_add(&t1, &t1, &s2); - - /* Extract t1 and write public key */ - polyveck_caddq(&t1); - polyveck_power2round(&t1, &t0, &t1); - pack_pk(pk, rho, &t1); - - /* Compute H(rho, t1) and write secret key */ - shake256(tr, TRBYTES, pk, CRYPTO_PUBLICKEYBYTES); - pack_sk(sk, rho, tr, key, &t0, &s1, &s2); - - return 0; -} - -/************************************************* -* Name: crypto_sign_signature_internal -* -* Description: Computes signature. Internal API. -* -* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES) -* - size_t *siglen: pointer to output length of signature -* - uint8_t *m: pointer to message to be signed -* - size_t mlen: length of message -* - uint8_t *pre: pointer to prefix string -* - size_t prelen: length of prefix string -* - uint8_t *rnd: pointer to random seed -* - uint8_t *sk: pointer to bit-packed secret key -* -* Returns 0 (success) -**************************************************/ -int crypto_sign_signature_internal(uint8_t *sig, - size_t *siglen, - const uint8_t *m, - size_t mlen, - const uint8_t *pre, - size_t prelen, - const uint8_t rnd[RNDBYTES], - const uint8_t *sk) -{ - unsigned int n; - uint8_t seedbuf[2*SEEDBYTES + TRBYTES + 2*CRHBYTES]; - uint8_t *rho, *tr, *key, *mu, *rhoprime; - uint16_t nonce = 0; - polyvecl mat[K], s1, y, z; - polyveck t0, s2, w1, w0, h; - poly cp; - keccak_state state; - - rho = seedbuf; - tr = rho + SEEDBYTES; - key = tr + TRBYTES; - mu = key + SEEDBYTES; - rhoprime = mu + CRHBYTES; - unpack_sk(rho, tr, key, &t0, &s1, &s2, sk); - - /* Compute mu = CRH(tr, pre, msg) */ - shake256_init(&state); - shake256_absorb(&state, tr, TRBYTES); - shake256_absorb(&state, pre, prelen); - shake256_absorb(&state, m, mlen); - shake256_finalize(&state); - shake256_squeeze(mu, CRHBYTES, &state); - - /* Compute rhoprime = CRH(key, rnd, mu) */ - shake256_init(&state); - shake256_absorb(&state, key, SEEDBYTES); - shake256_absorb(&state, rnd, RNDBYTES); - shake256_absorb(&state, mu, CRHBYTES); - shake256_finalize(&state); - shake256_squeeze(rhoprime, CRHBYTES, &state); - - /* Expand matrix and transform vectors */ - polyvec_matrix_expand(mat, rho); - polyvecl_ntt(&s1); - polyveck_ntt(&s2); - polyveck_ntt(&t0); - -rej: - /* Sample intermediate vector y */ - polyvecl_uniform_gamma1(&y, rhoprime, nonce++); - - /* Matrix-vector multiplication */ - z = y; - polyvecl_ntt(&z); - polyvec_matrix_pointwise_montgomery(&w1, mat, &z); - polyveck_reduce(&w1); - polyveck_invntt_tomont(&w1); - - /* Decompose w and call the random oracle */ - polyveck_caddq(&w1); - polyveck_decompose(&w1, &w0, &w1); - polyveck_pack_w1(sig, &w1); - - shake256_init(&state); - shake256_absorb(&state, mu, CRHBYTES); - shake256_absorb(&state, sig, K*POLYW1_PACKEDBYTES); - shake256_finalize(&state); - shake256_squeeze(sig, CTILDEBYTES, &state); - poly_challenge(&cp, sig); - poly_ntt(&cp); - - /* Compute z, reject if it reveals secret */ - polyvecl_pointwise_poly_montgomery(&z, &cp, &s1); - polyvecl_invntt_tomont(&z); - polyvecl_add(&z, &z, &y); - polyvecl_reduce(&z); - if(polyvecl_chknorm(&z, GAMMA1 - BETA)) - goto rej; - - /* Check that subtracting cs2 does not change high bits of w and low bits - * do not reveal secret information */ - polyveck_pointwise_poly_montgomery(&h, &cp, &s2); - polyveck_invntt_tomont(&h); - polyveck_sub(&w0, &w0, &h); - polyveck_reduce(&w0); - if(polyveck_chknorm(&w0, GAMMA2 - BETA)) - goto rej; - - /* Compute hints for w1 */ - polyveck_pointwise_poly_montgomery(&h, &cp, &t0); - polyveck_invntt_tomont(&h); - polyveck_reduce(&h); - if(polyveck_chknorm(&h, GAMMA2)) - goto rej; - - polyveck_add(&w0, &w0, &h); - n = polyveck_make_hint(&h, &w0, &w1); - if(n > OMEGA) - goto rej; - - /* Write signature */ - pack_sig(sig, sig, &z, &h); - *siglen = CRYPTO_BYTES; - return 0; -} - -/************************************************* -* Name: crypto_sign_signature -* -* Description: Computes signature. -* -* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES) -* - size_t *siglen: pointer to output length of signature -* - uint8_t *m: pointer to message to be signed -* - size_t mlen: length of message -* - uint8_t *ctx: pointer to contex string -* - size_t ctxlen: length of contex string -* - uint8_t *sk: pointer to bit-packed secret key -* -* Returns 0 (success) or -1 (context string too long) -**************************************************/ -int crypto_sign_signature(uint8_t *sig, - size_t *siglen, - const uint8_t *m, - size_t mlen, - const uint8_t *ctx, - size_t ctxlen, - const uint8_t *sk) -{ - size_t i; - uint8_t pre[257]; - uint8_t rnd[RNDBYTES]; - - if(ctxlen > 255) - return -1; - - /* Prepare pre = (0, ctxlen, ctx) */ - pre[0] = 0; - pre[1] = ctxlen; - for(i = 0; i < ctxlen; i++) - pre[2 + i] = ctx[i]; - -#ifdef DILITHIUM_RANDOMIZED_SIGNING - randombytes(rnd, RNDBYTES); -#else - for(i=0;i 255) - return -1; - - pre[0] = 0; - pre[1] = ctxlen; - for(i = 0; i < ctxlen; i++) - pre[2 + i] = ctx[i]; - - return crypto_sign_verify_internal(sig,siglen,m,mlen,pre,2+ctxlen,pk); -} - -/************************************************* -* Name: crypto_sign_open -* -* Description: Verify signed message. -* -* Arguments: - uint8_t *m: pointer to output message (allocated -* array with smlen bytes), can be equal to sm -* - size_t *mlen: pointer to output length of message -* - const uint8_t *sm: pointer to signed message -* - size_t smlen: length of signed message -* - const uint8_t *ctx: pointer to context tring -* - size_t ctxlen: length of context string -* - const uint8_t *pk: pointer to bit-packed public key -* -* Returns 0 if signed message could be verified correctly and -1 otherwise -**************************************************/ -int crypto_sign_open(uint8_t *m, - size_t *mlen, - const uint8_t *sm, - size_t smlen, - const uint8_t *ctx, - size_t ctxlen, - const uint8_t *pk) -{ - size_t i; - - if(smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - if(crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, ctx, ctxlen, pk)) - goto badsig; - else { - /* All good, copy msg, return 0 */ - for(i = 0; i < *mlen; ++i) - m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = 0; - for(i = 0; i < smlen; ++i) - m[i] = 0; - - return -1; -} diff --git a/dilithium/ref/sign.h b/dilithium/ref/sign.h deleted file mode 100644 index 2741e8f..0000000 --- a/dilithium/ref/sign.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SIGN_H -#define SIGN_H - -#include -#include -#include "params.h" -#include "polyvec.h" -#include "poly.h" - -#define crypto_sign_keypair DILITHIUM_NAMESPACE(keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -#define crypto_sign_signature_internal DILITHIUM_NAMESPACE(signature_internal) -int crypto_sign_signature_internal(uint8_t *sig, - size_t *siglen, - const uint8_t *m, - size_t mlen, - const uint8_t *pre, - size_t prelen, - const uint8_t rnd[RNDBYTES], - const uint8_t *sk); - -#define crypto_sign_signature DILITHIUM_NAMESPACE(signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -#define crypto_sign DILITHIUM_NAMESPACETOP -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *sk); - -#define crypto_sign_verify_internal DILITHIUM_NAMESPACE(verify_internal) -int crypto_sign_verify_internal(const uint8_t *sig, - size_t siglen, - const uint8_t *m, - size_t mlen, - const uint8_t *pre, - size_t prelen, - const uint8_t *pk); - -#define crypto_sign_verify DILITHIUM_NAMESPACE(verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - -#define crypto_sign_open DILITHIUM_NAMESPACE(open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *ctx, size_t ctxlen, - const uint8_t *pk); - -#endif diff --git a/dilithium/ref/symmetric-shake.c b/dilithium/ref/symmetric-shake.c deleted file mode 100644 index 11ec09c..0000000 --- a/dilithium/ref/symmetric-shake.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include "params.h" -#include "symmetric.h" -#include "fips202.h" - -void dilithium_shake128_stream_init(keccak_state *state, const uint8_t seed[SEEDBYTES], uint16_t nonce) -{ - uint8_t t[2]; - t[0] = nonce; - t[1] = nonce >> 8; - - shake128_init(state); - shake128_absorb(state, seed, SEEDBYTES); - shake128_absorb(state, t, 2); - shake128_finalize(state); -} - -void dilithium_shake256_stream_init(keccak_state *state, const uint8_t seed[CRHBYTES], uint16_t nonce) -{ - uint8_t t[2]; - t[0] = nonce; - t[1] = nonce >> 8; - - shake256_init(state); - shake256_absorb(state, seed, CRHBYTES); - shake256_absorb(state, t, 2); - shake256_finalize(state); -} diff --git a/dilithium/ref/symmetric.h b/dilithium/ref/symmetric.h deleted file mode 100644 index cba12d1..0000000 --- a/dilithium/ref/symmetric.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef SYMMETRIC_H -#define SYMMETRIC_H - -#include -#include "params.h" - -#include "fips202.h" - -typedef keccak_state stream128_state; -typedef keccak_state stream256_state; - -#define dilithium_shake128_stream_init DILITHIUM_NAMESPACE(dilithium_shake128_stream_init) -void dilithium_shake128_stream_init(keccak_state *state, - const uint8_t seed[SEEDBYTES], - uint16_t nonce); - -#define dilithium_shake256_stream_init DILITHIUM_NAMESPACE(dilithium_shake256_stream_init) -void dilithium_shake256_stream_init(keccak_state *state, - const uint8_t seed[CRHBYTES], - uint16_t nonce); - -#define STREAM128_BLOCKBYTES SHAKE128_RATE -#define STREAM256_BLOCKBYTES SHAKE256_RATE - -#define stream128_init(STATE, SEED, NONCE) \ - dilithium_shake128_stream_init(STATE, SEED, NONCE) -#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - shake128_squeezeblocks(OUT, OUTBLOCKS, STATE) -#define stream256_init(STATE, SEED, NONCE) \ - dilithium_shake256_stream_init(STATE, SEED, NONCE) -#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) - -#endif diff --git a/dilithium/ref/test/.gitignore b/dilithium/ref/test/.gitignore deleted file mode 100644 index 99b3f73..0000000 --- a/dilithium/ref/test/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -test_dilithium2 -test_dilithium3 -test_dilithium5 -test_vectors2 -test_vectors3 -test_vectors5 -test_speed2 -test_speed3 -test_speed5 -test_mul diff --git a/dilithium/ref/test/cpucycles.c b/dilithium/ref/test/cpucycles.c deleted file mode 100644 index ccbf54d..0000000 --- a/dilithium/ref/test/cpucycles.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include "cpucycles.h" - -uint64_t cpucycles_overhead(void) { - uint64_t t0, t1, overhead = -1LL; - unsigned int i; - - for(i=0;i<100000;i++) { - t0 = cpucycles(); - __asm__ volatile(""); - t1 = cpucycles(); - if(t1 - t0 < overhead) - overhead = t1 - t0; - } - - return overhead; -} diff --git a/dilithium/ref/test/cpucycles.h b/dilithium/ref/test/cpucycles.h deleted file mode 100644 index 7b7b9f7..0000000 --- a/dilithium/ref/test/cpucycles.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef CPUCYCLES_H -#define CPUCYCLES_H - -#include - -#ifdef USE_RDPMC /* Needs echo 2 > /sys/devices/cpu/rdpmc */ - -static inline uint64_t cpucycles(void) { - const uint32_t ecx = (1U << 30) + 1; - uint64_t result; - - __asm__ volatile ("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" - : "=a" (result) : "c" (ecx) : "rdx"); - - return result; -} - -#else - -static inline uint64_t cpucycles(void) { - uint64_t result; - - __asm__ volatile ("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" - : "=a" (result) : : "%rdx"); - - return result; -} - -#endif - -uint64_t cpucycles_overhead(void); - -#endif diff --git a/dilithium/ref/test/speed_print.c b/dilithium/ref/test/speed_print.c deleted file mode 100644 index 59f147d..0000000 --- a/dilithium/ref/test/speed_print.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include -#include "cpucycles.h" -#include "speed_print.h" - -static int cmp_uint64(const void *a, const void *b) { - if(*(uint64_t *)a < *(uint64_t *)b) return -1; - if(*(uint64_t *)a > *(uint64_t *)b) return 1; - return 0; -} - -static uint64_t median(uint64_t *l, size_t llen) { - qsort(l,llen,sizeof(uint64_t),cmp_uint64); - - if(llen%2) return l[llen/2]; - else return (l[llen/2-1]+l[llen/2])/2; -} - -static uint64_t average(uint64_t *t, size_t tlen) { - size_t i; - uint64_t acc=0; - - for(i=0;i -#include - -void print_results(const char *s, uint64_t *t, size_t tlen); - -#endif diff --git a/dilithium/ref/test/test_dilithium.c b/dilithium/ref/test/test_dilithium.c deleted file mode 100644 index 66beb4c..0000000 --- a/dilithium/ref/test/test_dilithium.c +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include -#include "../randombytes.h" -#include "../sign.h" - -#define MLEN 59 -#define CTXLEN 14 -#define NTESTS 10000 - -int main(void) -{ - size_t i, j; - int ret; - size_t mlen, smlen; - uint8_t b; - uint8_t ctx[CTXLEN] = {0}; - uint8_t m[MLEN + CRYPTO_BYTES]; - uint8_t m2[MLEN + CRYPTO_BYTES]; - uint8_t sm[MLEN + CRYPTO_BYTES]; - uint8_t pk[CRYPTO_PUBLICKEYBYTES]; - uint8_t sk[CRYPTO_SECRETKEYBYTES]; - - snprintf((char*)ctx,CTXLEN,"test_dilitium"); - - for(i = 0; i < NTESTS; ++i) { - randombytes(m, MLEN); - - crypto_sign_keypair(pk, sk); - crypto_sign(sm, &smlen, m, MLEN, ctx, CTXLEN, sk); - ret = crypto_sign_open(m2, &mlen, sm, smlen, ctx, CTXLEN, pk); - - if(ret) { - fprintf(stderr, "Verification failed\n"); - return -1; - } - if(smlen != MLEN + CRYPTO_BYTES) { - fprintf(stderr, "Signed message lengths wrong\n"); - return -1; - } - if(mlen != MLEN) { - fprintf(stderr, "Message lengths wrong\n"); - return -1; - } - for(j = 0; j < MLEN; ++j) { - if(m2[j] != m[j]) { - fprintf(stderr, "Messages don't match\n"); - return -1; - } - } - - randombytes((uint8_t *)&j, sizeof(j)); - do { - randombytes(&b, 1); - } while(!b); - sm[j % (MLEN + CRYPTO_BYTES)] += b; - ret = crypto_sign_open(m2, &mlen, sm, smlen, ctx, CTXLEN, pk); - if(!ret) { - fprintf(stderr, "Trivial forgeries possible\n"); - return -1; - } - } - - printf("CRYPTO_PUBLICKEYBYTES = %d\n", CRYPTO_PUBLICKEYBYTES); - printf("CRYPTO_SECRETKEYBYTES = %d\n", CRYPTO_SECRETKEYBYTES); - printf("CRYPTO_BYTES = %d\n", CRYPTO_BYTES); - - return 0; -} diff --git a/dilithium/ref/test/test_mul.c b/dilithium/ref/test/test_mul.c deleted file mode 100644 index 4633c11..0000000 --- a/dilithium/ref/test/test_mul.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include "../params.h" -#include "../randombytes.h" -#include "../poly.h" - -#define NTESTS 100000 - -static void poly_naivemul(poly *c, const poly *a, const poly *b) { - unsigned int i,j; - int32_t r[2*N] = {0}; - - for(i = 0; i < N; i++) - for(j = 0; j < N; j++) - r[i+j] = (r[i+j] + (int64_t)a->coeffs[i]*b->coeffs[j]) % Q; - - for(i = N; i < 2*N; i++) - r[i-N] = (r[i-N] - r[i]) % Q; - - for(i = 0; i < N; i++) - c->coeffs[i] = r[i]; -} - -int main(void) { - unsigned int i, j; - uint8_t seed[SEEDBYTES]; - uint16_t nonce = 0; - poly a, b, c, d; - - randombytes(seed, sizeof(seed)); - for(i = 0; i < NTESTS; ++i) { - poly_uniform(&a, seed, nonce++); - poly_uniform(&b, seed, nonce++); - - c = a; - poly_ntt(&c); - for(j = 0; j < N; ++j) - c.coeffs[j] = (int64_t)c.coeffs[j]*-114592 % Q; - poly_invntt_tomont(&c); - for(j = 0; j < N; ++j) { - if((c.coeffs[j] - a.coeffs[j]) % Q) - fprintf(stderr, "ERROR in ntt/invntt: c[%d] = %d != %d\n", - j, c.coeffs[j]%Q, a.coeffs[j]); - } - - poly_naivemul(&c, &a, &b); - poly_ntt(&a); - poly_ntt(&b); - poly_pointwise_montgomery(&d, &a, &b); - poly_invntt_tomont(&d); - - for(j = 0; j < N; ++j) { - if((d.coeffs[j] - c.coeffs[j]) % Q) - fprintf(stderr, "ERROR in multiplication: d[%d] = %d != %d\n", - j, d.coeffs[j], c.coeffs[j]); - } - } - - return 0; -} diff --git a/dilithium/ref/test/test_speed.c b/dilithium/ref/test/test_speed.c deleted file mode 100644 index 688d930..0000000 --- a/dilithium/ref/test/test_speed.c +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include "../sign.h" -#include "../poly.h" -#include "../polyvec.h" -#include "../params.h" -#include "cpucycles.h" -#include "speed_print.h" - -#define NTESTS 1000 - -uint64_t t[NTESTS]; - -int main(void) -{ - unsigned int i; - size_t siglen; - uint8_t pk[CRYPTO_PUBLICKEYBYTES]; - uint8_t sk[CRYPTO_SECRETKEYBYTES]; - uint8_t sig[CRYPTO_BYTES]; - uint8_t seed[CRHBYTES]; - polyvecl mat[K]; - poly *a = &mat[0].vec[0]; - poly *b = &mat[0].vec[1]; - poly *c = &mat[0].vec[2]; - - for(i = 0; i < NTESTS; ++i) { - t[i] = cpucycles(); - polyvec_matrix_expand(mat, seed); - } - print_results("polyvec_matrix_expand:", t, NTESTS); - - for(i = 0; i < NTESTS; ++i) { - t[i] = cpucycles(); - poly_uniform_eta(a, seed, 0); - } - print_results("poly_uniform_eta:", t, NTESTS); - - for(i = 0; i < NTESTS; ++i) { - t[i] = cpucycles(); - poly_uniform_gamma1(a, seed, 0); - } - print_results("poly_uniform_gamma1:", t, NTESTS); - - for(i = 0; i < NTESTS; ++i) { - t[i] = cpucycles(); - poly_ntt(a); - } - print_results("poly_ntt:", t, NTESTS); - - for(i = 0; i < NTESTS; ++i) { - t[i] = cpucycles(); - poly_invntt_tomont(a); - } - print_results("poly_invntt_tomont:", t, NTESTS); - - for(i = 0; i < NTESTS; ++i) { - t[i] = cpucycles(); - poly_pointwise_montgomery(c, a, b); - } - print_results("poly_pointwise_montgomery:", t, NTESTS); - - for(i = 0; i < NTESTS; ++i) { - t[i] = cpucycles(); - poly_challenge(c, seed); - } - print_results("poly_challenge:", t, NTESTS); - - for(i = 0; i < NTESTS; ++i) { - t[i] = cpucycles(); - crypto_sign_keypair(pk, sk); - } - print_results("Keypair:", t, NTESTS); - - for(i = 0; i < NTESTS; ++i) { - t[i] = cpucycles(); - crypto_sign_signature(sig, &siglen, sig, CRHBYTES, NULL, 0, sk); - } - print_results("Sign:", t, NTESTS); - - for(i = 0; i < NTESTS; ++i) { - t[i] = cpucycles(); - crypto_sign_verify(sig, CRYPTO_BYTES, sig, CRHBYTES, NULL, 0, pk); - } - print_results("Verify:", t, NTESTS); - - return 0; -} diff --git a/dilithium/ref/test/test_vectors.c b/dilithium/ref/test/test_vectors.c deleted file mode 100644 index 2829286..0000000 --- a/dilithium/ref/test/test_vectors.c +++ /dev/null @@ -1,251 +0,0 @@ -#include -#include -#include -#include -#include "../randombytes.h" -#include "../fips202.h" -#include "../params.h" -#include "../sign.h" -#include "../poly.h" -#include "../polyvec.h" -#include "../packing.h" - -#define MLEN 32 -#define CTXLEN 13 -#define NVECTORS 10000 - -/* Initital state after absorbing empty string - * Permute before squeeze is achieved by setting pos to SHAKE128_RATE */ -static keccak_state rngstate = {{0x1F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (1ULL << 63), 0, 0, 0, 0}, SHAKE128_RATE}; - -void randombytes(uint8_t *x,size_t xlen) { - shake128_squeeze(x, xlen, &rngstate); -} - -int main(void) { - unsigned int i, j, k, l; - uint8_t pk[CRYPTO_PUBLICKEYBYTES]; - uint8_t sk[CRYPTO_SECRETKEYBYTES]; - uint8_t sig[CRYPTO_BYTES]; - uint8_t m[MLEN]; - uint8_t ctx[CTXLEN] = {0}; - uint8_t seed[CRHBYTES]; - uint8_t buf[CRYPTO_SECRETKEYBYTES]; - size_t siglen; - poly c, tmp; - polyvecl s, y, mat[K]; - polyveck w, w1, w0, t1, t0, h; - - snprintf((char*)ctx,CTXLEN,"test_vectors"); - - for(i = 0; i < NVECTORS; ++i) { - printf("count = %u\n", i); - - randombytes(m, MLEN); - printf("m = "); - for(j = 0; j < MLEN; ++j) - printf("%02x", m[j]); - printf("\n"); - - crypto_sign_keypair(pk, sk); - shake256(buf, 32, pk, CRYPTO_PUBLICKEYBYTES); - printf("pk = "); - for(j = 0; j < 32; ++j) - printf("%02x", buf[j]); - printf("\n"); - shake256(buf, 32, sk, CRYPTO_SECRETKEYBYTES); - printf("sk = "); - for(j = 0; j < 32; ++j) - printf("%02x", buf[j]); - printf("\n"); - - crypto_sign_signature(sig, &siglen, m, MLEN, ctx, CTXLEN, sk); - shake256(buf, 32, sig, CRYPTO_BYTES); - printf("sig = "); - for(j = 0; j < 32; ++j) - printf("%02x", buf[j]); - printf("\n"); - - if(crypto_sign_verify(sig, siglen, m, MLEN, ctx, CTXLEN, pk)) - fprintf(stderr,"Signature verification failed!\n"); - - randombytes(seed, sizeof(seed)); - printf("seed = "); - for(j = 0; j < sizeof(seed); ++j) - printf("%02X", seed[j]); - printf("\n"); - - polyvec_matrix_expand(mat, seed); - printf("A = (["); - for(j = 0; j < K; ++j) { - for(k = 0; k < L; ++k) { - for(l = 0; l < N; ++l) { - printf("%8d", mat[j].vec[k].coeffs[l]); - if(l < N-1) printf(", "); - else if(k < L-1) printf("], ["); - else if(j < K-1) printf("];\n ["); - else printf("])\n"); - } - } - } - - polyvecl_uniform_eta(&s, seed, 0); - - polyeta_pack(buf, &s.vec[0]); - polyeta_unpack(&tmp, buf); - for(j = 0; j < N; ++j) - if(tmp.coeffs[j] != s.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in polyeta_(un)pack!\n"); - - if(polyvecl_chknorm(&s, ETA+1)) - fprintf(stderr, "ERROR in polyvecl_chknorm(&s ,ETA+1)!\n"); - - printf("s = (["); - for(j = 0; j < L; ++j) { - for(k = 0; k < N; ++k) { - printf("%3d", s.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < L-1) printf("],\n ["); - else printf("])\n"); - } - } - - polyvecl_uniform_gamma1(&y, seed, 0); - - polyz_pack(buf, &y.vec[0]); - polyz_unpack(&tmp, buf); - for(j = 0; j < N; ++j) - if(tmp.coeffs[j] != y.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in polyz_(un)pack!\n"); - - if(polyvecl_chknorm(&y, GAMMA1+1)) - fprintf(stderr, "ERROR in polyvecl_chknorm(&y, GAMMA1)!\n"); - - printf("y = (["); - for(j = 0; j < L; ++j) { - for(k = 0; k < N; ++k) { - printf("%8d", y.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < L-1) printf("],\n ["); - else printf("])\n"); - } - } - - polyvecl_ntt(&y); - polyvec_matrix_pointwise_montgomery(&w, mat, &y); - polyveck_reduce(&w); - polyveck_invntt_tomont(&w); - polyveck_caddq(&w); - polyveck_decompose(&w1, &w0, &w); - - for(j = 0; j < N; ++j) { - tmp.coeffs[j] = w1.vec[0].coeffs[j]*2*GAMMA2 + w0.vec[0].coeffs[j]; - if(tmp.coeffs[j] < 0) tmp.coeffs[j] += Q; - if(tmp.coeffs[j] != w.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in poly_decompose!\n"); - } - - polyw1_pack(buf, &w1.vec[0]); -#if GAMMA2 == (Q-1)/32 - for(j = 0; j < N/2; ++j) { - tmp.coeffs[2*j+0] = buf[j] & 0xF; - tmp.coeffs[2*j+1] = buf[j] >> 4; - if(tmp.coeffs[2*j+0] != w1.vec[0].coeffs[2*j+0] - || tmp.coeffs[2*j+1] != w1.vec[0].coeffs[2*j+1]) - fprintf(stderr, "ERROR in polyw1_pack!\n"); - } -#endif - -#if GAMMA2 == (Q-1)/32 - if(polyveck_chknorm(&w1, 16)) - fprintf(stderr, "ERROR in polyveck_chknorm(&w1, 16)!\n"); -#elif GAMMA2 == (Q-1)/88 - if(polyveck_chknorm(&w1, 44)) - fprintf(stderr, "ERROR in polyveck_chknorm(&w1, 44)!\n"); -#endif - if(polyveck_chknorm(&w0, GAMMA2 + 1)) - fprintf(stderr, "ERROR in polyveck_chknorm(&w0, GAMMA2+1)!\n"); - - printf("w1 = (["); - for(j = 0; j < K; ++j) { - for(k = 0; k < N; ++k) { - printf("%2d", w1.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < K-1) printf("],\n ["); - else printf("])\n"); - } - } - printf("w0 = (["); - for(j = 0; j < K; ++j) { - for(k = 0; k < N; ++k) { - printf("%8d", w0.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < K-1) printf("],\n ["); - else printf("])\n"); - } - } - - polyveck_power2round(&t1, &t0, &w); - - for(j = 0; j < N; ++j) { - tmp.coeffs[j] = (t1.vec[0].coeffs[j] << D) + t0.vec[0].coeffs[j]; - if(tmp.coeffs[j] != w.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in poly_power2round!\n"); - } - - polyt1_pack(buf, &t1.vec[0]); - polyt1_unpack(&tmp, buf); - for(j = 0; j < N; ++j) { - if(tmp.coeffs[j] != t1.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in polyt1_(un)pack!\n"); - } - polyt0_pack(buf, &t0.vec[0]); - polyt0_unpack(&tmp, buf); - for(j = 0; j < N; ++j) { - if(tmp.coeffs[j] != t0.vec[0].coeffs[j]) - fprintf(stderr, "ERROR in polyt0_(un)pack!\n"); - } - - if(polyveck_chknorm(&t1, 1024)) - fprintf(stderr, "ERROR in polyveck_chknorm(&t1, 1024)!\n"); - if(polyveck_chknorm(&t0, (1U << (D-1)) + 1)) - fprintf(stderr, "ERROR in polyveck_chknorm(&t0, (1 << (D-1)) + 1)!\n"); - - printf("t1 = (["); - for(j = 0; j < K; ++j) { - for(k = 0; k < N; ++k) { - printf("%3d", t1.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < K-1) printf("],\n ["); - else printf("])\n"); - } - } - printf("t0 = (["); - for(j = 0; j < K; ++j) { - for(k = 0; k < N; ++k) { - printf("%5d", t0.vec[j].coeffs[k]); - if(k < N-1) printf(", "); - else if(j < K-1) printf("],\n ["); - else printf("])\n"); - } - } - - poly_challenge(&c, seed); - printf("c = ["); - for(j = 0; j < N; ++j) { - printf("%2d", c.coeffs[j]); - if(j < N-1) printf(", "); - else printf("]\n"); - } - - polyveck_make_hint(&h, &w0, &w1); - pack_sig(buf, seed, &y, &h); - unpack_sig(seed, &y, &w, buf); - if(memcmp(&h,&w,sizeof(h))) - fprintf(stderr, "ERROR in (un)pack_sig!\n"); - - printf("\n"); - } - - return 0; -} diff --git a/dilithium/runlcov.sh b/dilithium/runlcov.sh deleted file mode 100755 index a94bb8b..0000000 --- a/dilithium/runlcov.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -e - -cd ref - -for alg in 2 3 5; do - make -B test/test_dilithium$alg CFLAGS="-O0 -g --coverage" - ./test/test_dilithium$alg - lcov -c -d . -o dilithium$alg.lcov - lcov -z -d . - rm test/test_dilithium$alg -done - -lcov -o dilithium.lcov \ - -a dilithium2.lcov \ - -a dilithium3.lcov \ - -a dilithium5.lcov \ - -lcov -r dilithium.lcov -o dilithium.lcov \ - '*/test/test_dilithium.c' - -exit 0 diff --git a/dilithium/runtests.sh b/dilithium/runtests.sh deleted file mode 100755 index f0b0bc5..0000000 --- a/dilithium/runtests.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -e -nproc="${nproc:-2}" - -ARCH="${ARCH:-amd64}" -ARCH="${TRAVIS_CPU_ARCH:-$ARCH}" - -if [ "$ARCH" = "amd64" -a "$TRAVIS_OS_NAME" != "osx" ]; then - DIRS="ref avx2" -else - DIRS="ref" -fi - -if [ "$ARCH" = "amd64" -o "$ARCH" = "arm64" ]; then - export CC=/usr/bin/clang - export CFLAGS="-fsanitize=undefined,address ${CFLAGS}" -fi - -for dir in $DIRS; do - make -j$(nproc) -C $dir clean - make -j$(nproc) -C $dir - for alg in 2 3 5; do - #valgrind --vex-guest-max-insns=25 ./$dir/test/test_dilithium$alg - ./$dir/test/test_dilithium$alg & - PID1=$! - echo testvec$alg - ./$dir/test/test_vectors$alg > tvecs$alg & - PID2=$! - wait $PID1 $PID2 - done - shasum -a256 -c SHA256SUMS -done - -exit 0 diff --git a/sphincsplus/.github/workflows/test-haraka-aesni.yml b/sphincsplus/.github/workflows/test-haraka-aesni.yml deleted file mode 100644 index 4f0e713..0000000 --- a/sphincsplus/.github/workflows/test-haraka-aesni.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Tests for haraka-aesni implementation - -on: - - push - - pull_request - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - size: - - 128 - - 192 - - 256 - option: - - s - - f - thash: - - simple - - robust - steps: - - uses: actions/checkout@v1 - - name: Run make - run: | - make -C haraka-aesni THASH=${{ matrix.thash }} clean - make -C haraka-aesni THASH=${{ matrix.thash }} PARAMS=sphincs-haraka-${{ matrix.size }}${{ matrix.option }} tests - make -C haraka-aesni THASH=${{ matrix.thash }} PARAMS=sphincs-haraka-${{ matrix.size }}${{ matrix.option }} test - make -C haraka-aesni THASH=${{ matrix.thash }} PARAMS=sphincs-haraka-${{ matrix.size }}${{ matrix.option }} PQCgenKAT_sign - - name: Run PQCgenKAT_sign - run: python3 vectors.py sphincs-haraka-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} haraka-aesni - -# vim: set ft=yaml ts=2 sw=2 et : diff --git a/sphincsplus/.github/workflows/test-ref.yml b/sphincsplus/.github/workflows/test-ref.yml deleted file mode 100644 index b97ded2..0000000 --- a/sphincsplus/.github/workflows/test-ref.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Tests for ref implementation - -on: - - push - - pull_request - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - hash: - - sha2 - - shake - - haraka - size: - - 128 - - 192 - - 256 - option: - - s - - f - thash: - - simple - - robust - steps: - - uses: actions/checkout@v1 - - name: Run make - run: | - make -C ref HASH=${{ matrix.hash }} THASH=${{ matrix.thash }} clean - make -C ref HASH=${{ matrix.hash }} THASH=${{ matrix.thash }} PARAMS=sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }} tests - make -C ref HASH=${{ matrix.hash }} THASH=${{ matrix.thash }} PARAMS=sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }} test - make -C ref THASH=${{ matrix.thash }} PQCgenKAT_sign - - name: Run PQCgenKAT_sign - run: python3 vectors.py sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} ref - -# vim: set ft=yaml ts=2 sw=2 et : diff --git a/sphincsplus/.github/workflows/test-sha2-avx2.yml b/sphincsplus/.github/workflows/test-sha2-avx2.yml deleted file mode 100644 index d0dd58e..0000000 --- a/sphincsplus/.github/workflows/test-sha2-avx2.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Tests for sha2-avx2 implementation - -on: - - push - - pull_request - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - size: - - 128 - - 192 - - 256 - option: - - s - - f - thash: - - simple - - robust - steps: - - uses: actions/checkout@v1 - - name: Run make - run: | - make -C sha2-avx2 THASH=${{ matrix.thash }} clean - make -C sha2-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-sha2-${{ matrix.size }}${{ matrix.option }} tests - make -C sha2-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-sha2-${{ matrix.size }}${{ matrix.option }} test - make -C sha2-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-sha2-${{ matrix.size }}${{ matrix.option }} PQCgenKAT_sign - - name: Run PQCgenKAT_sign - run: python3 vectors.py sphincs-sha2-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} sha2-avx2 - -# vim: set ft=yaml ts=2 sw=2 et : diff --git a/sphincsplus/.github/workflows/test-shake-avx2.yml b/sphincsplus/.github/workflows/test-shake-avx2.yml deleted file mode 100644 index 4e6ddea..0000000 --- a/sphincsplus/.github/workflows/test-shake-avx2.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Tests for shake-avx2 implementation - -on: - - push - - pull_request - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - size: - - 128 - - 192 - - 256 - option: - - s - - f - thash: - - simple - - robust - steps: - - uses: actions/checkout@v1 - - name: Run make - run: | - make -C shake-avx2 THASH=${{ matrix.thash }} clean - make -C shake-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-shake-${{ matrix.size }}${{ matrix.option }} tests - make -C shake-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-shake-${{ matrix.size }}${{ matrix.option }} test - make -C shake-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-shake-${{ matrix.size }}${{ matrix.option }} PQCgenKAT_sign - - name: Run PQCgenKAT_sign - run: python3 vectors.py sphincs-shake-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} shake-avx2 - -# vim: set ft=yaml ts=2 sw=2 et : diff --git a/sphincsplus/.reuse/dep5 b/sphincsplus/.reuse/dep5 deleted file mode 100644 index 8d2def9..0000000 --- a/sphincsplus/.reuse/dep5 +++ /dev/null @@ -1,15 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: SPHINCS+ -Upstream-Contact: contact@sphincs.org -Souce: https://github.com/sphincs/sphincsplus - -Files: * -License: LicenseRef-SPHINCS-PLUS-Public-Domain OR CC0-1.0 OR 0BSD OR MIT-0 - -Files: ref/haraka.c -Copyright: 2016 Thomas Pornin and SPHINCS+ team -License: (LicenseRef-SPHINCS-PLUS-Public-Domain OR CC0-1.0 OR 0BSD OR MIT-0) AND MIT - -Files: ref/PQCgenKAT_sign.c ref/rng.c ref/rng.h -Copyright: 2017 Bassham, Lawrence E (Fed). -License: All rights reserved. diff --git a/sphincsplus/LICENSE b/sphincsplus/LICENSE deleted file mode 100644 index ca88ec4..0000000 --- a/sphincsplus/LICENSE +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-License-Identifier: (LicenseRef-SPHINCS-PLUS-Public-Domain OR CC0-1.0 OR 0BSD OR MIT-0) AND MIT - diff --git a/sphincsplus/LICENSES/0BSD.txt b/sphincsplus/LICENSES/0BSD.txt deleted file mode 100644 index c19ef1c..0000000 --- a/sphincsplus/LICENSES/0BSD.txt +++ /dev/null @@ -1,12 +0,0 @@ -BSD Zero Clause License - -Permission to use, copy, modify, and/or distribute this software for -any purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE -FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY -DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN -AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/sphincsplus/LICENSES/CC0-1.0.txt b/sphincsplus/LICENSES/CC0-1.0.txt deleted file mode 100644 index 6ca207e..0000000 --- a/sphincsplus/LICENSES/CC0-1.0.txt +++ /dev/null @@ -1,122 +0,0 @@ -Creative Commons Legal Code - -CC0 1.0 Universal - - CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE - LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN - ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS - INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES - REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS - PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM - THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED - HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator -and subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for -the purpose of contributing to a commons of creative, cultural and -scientific works ("Commons") that the public can reliably and without fear -of later claims of infringement build upon, modify, incorporate in other -works, reuse and redistribute as freely as possible in any form whatsoever -and for any purposes, including without limitation commercial purposes. -These owners may contribute to the Commons to promote the ideal of a free -culture and the further production of creative, cultural and scientific -works, or to gain reputation or greater distribution for their Work in -part through the use and efforts of others. - -For these and/or other purposes and motivations, and without any -expectation of additional consideration or compensation, the person -associating CC0 with a Work (the "Affirmer"), to the extent that he or she -is an owner of Copyright and Related Rights in the Work, voluntarily -elects to apply CC0 to the Work and publicly distribute the Work under its -terms, with knowledge of his or her Copyright and Related Rights in the -Work and the meaning and intended legal effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not -limited to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, - communicate, and translate a Work; - ii. moral rights retained by the original author(s) and/or performer(s); -iii. publicity and privacy rights pertaining to a person's image or - likeness depicted in a Work; - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - v. rights protecting the extraction, dissemination, use and reuse of data - in a Work; - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation - thereof, including any amended or successor version of such - directive); and -vii. other similar, equivalent or corresponding rights throughout the - world based on applicable law or treaty, and any national - implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention -of, applicable law, Affirmer hereby overtly, fully, permanently, -irrevocably and unconditionally waives, abandons, and surrenders all of -Affirmer's Copyright and Related Rights and associated claims and causes -of action, whether now known or unknown (including existing as well as -future claims and causes of action), in the Work (i) in all territories -worldwide, (ii) for the maximum duration provided by applicable law or -treaty (including future time extensions), (iii) in any current or future -medium and for any number of copies, and (iv) for any purpose whatsoever, -including without limitation commercial, advertising or promotional -purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each -member of the public at large and to the detriment of Affirmer's heirs and -successors, fully intending that such Waiver shall not be subject to -revocation, rescission, cancellation, termination, or any other legal or -equitable action to disrupt the quiet enjoyment of the Work by the public -as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason -be judged legally invalid or ineffective under applicable law, then the -Waiver shall be preserved to the maximum extent permitted taking into -account Affirmer's express Statement of Purpose. In addition, to the -extent the Waiver is so judged Affirmer hereby grants to each affected -person a royalty-free, non transferable, non sublicensable, non exclusive, -irrevocable and unconditional license to exercise Affirmer's Copyright and -Related Rights in the Work (i) in all territories worldwide, (ii) for the -maximum duration provided by applicable law or treaty (including future -time extensions), (iii) in any current or future medium and for any number -of copies, and (iv) for any purpose whatsoever, including without -limitation commercial, advertising or promotional purposes (the -"License"). The License shall be deemed effective as of the date CC0 was -applied by Affirmer to the Work. Should any part of the License for any -reason be judged legally invalid or ineffective under applicable law, such -partial invalidity or ineffectiveness shall not invalidate the remainder -of the License, and in such case Affirmer hereby affirms that he or she -will not (i) exercise any of his or her remaining Copyright and Related -Rights in the Work or (ii) assert any associated claims and causes of -action with respect to the Work, in either case contrary to Affirmer's -express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - b. Affirmer offers the Work as-is and makes no representations or - warranties of any kind concerning the Work, express, implied, - statutory or otherwise, including without limitation warranties of - title, merchantability, fitness for a particular purpose, non - infringement, or the absence of latent or other defects, accuracy, or - the present or absence of errors, whether or not discoverable, all to - the greatest extent permissible under applicable law. - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without - limitation any person's Copyright and Related Rights in the Work. - Further, Affirmer disclaims responsibility for obtaining any necessary - consents, permissions or other rights required for any use of the - Work. - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to - this CC0 or use of the Work. - diff --git a/sphincsplus/LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt b/sphincsplus/LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt deleted file mode 100644 index 8c93d5a..0000000 --- a/sphincsplus/LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt +++ /dev/null @@ -1,2 +0,0 @@ -This work is hereby placed into the public domain. - diff --git a/sphincsplus/LICENSES/MIT-0.txt b/sphincsplus/LICENSES/MIT-0.txt deleted file mode 100644 index 11f9808..0000000 --- a/sphincsplus/LICENSES/MIT-0.txt +++ /dev/null @@ -1,15 +0,0 @@ -MIT No Attribution - -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. - -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. - diff --git a/sphincsplus/LICENSES/MIT.txt b/sphincsplus/LICENSES/MIT.txt deleted file mode 100644 index 66cb02b..0000000 --- a/sphincsplus/LICENSES/MIT.txt +++ /dev/null @@ -1,8 +0,0 @@ -MIT License - -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 (including the next paragraph) 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. - diff --git a/sphincsplus/README.md b/sphincsplus/README.md deleted file mode 100644 index 5948b7d..0000000 --- a/sphincsplus/README.md +++ /dev/null @@ -1,37 +0,0 @@ -## SPHINCS+ - -This repository contains the software that accompanies the [SPHINCS+ submission](https://sphincs.org/) to [NIST's Post-Quantum Cryptography](https://csrc.nist.gov/Projects/Post-Quantum-Cryptography) project. - -![][test-ref] -![][test-sha256-avx2] -![][test-shake256-avx2] -![][test-haraka-aesni] - -### Parameters - -The [SPHINCS+ specification](https://sphincs.org/data/sphincs+-specification.pdf) proposed a set of 36 named instances, specifying hash functions and concrete parameters for the security level, tree dimensions, WOTS+ and FORS. This reference implementation allows for more flexibility, as parameters can be specified in a `params.h` file. The proposed parameter sets have been predefined in `ref/params/params-*.h`, and the hash function can be varied by linking with the different implementations of `hash.h`, i.e., `hash_haraka.c`, `hash_sha2.c` and `hash_shake.c`, as well as different implementations of `thash.h`, i.e., `*_robust.c` and `*_simple.c`. This is demonstrated in the `Makefile`. See the table below for a summary of the parameter sets. These parameters target the NIST security categories 1, 3 and 5; for each category, there is a parameter set geared towards either small signatures or fast signature generation. - -| | n | h | d | log(t) | k | w | bit security | pk bytes | sk bytes | sig bytes | -| :------------ | -: | -: | -: | -----: | -: | --: | -----------: | -------: | -------: | --------: | -| SPHINCS+-128s | 16 | 63 | 7 | 12 | 14 | 16 | 133 | 32 | 64 | 7,856 | -| SPHINCS+-128f | 16 | 66 | 22 | 6 | 33 | 16 | 128 | 32 | 64 | 17,088 | -| SPHINCS+-192s | 24 | 63 | 7 | 14 | 17 | 16 | 193 | 48 | 96 | 16,224 | -| SPHINCS+-192f | 24 | 66 | 22 | 8 | 33 | 16 | 194 | 48 | 96 | 35,664 | -| SPHINCS+-256s | 32 | 64 | 8 | 14 | 22 | 16 | 255 | 64 | 128 | 29,792 | -| SPHINCS+-256f | 32 | 68 | 17 | 9 | 35 | 16 | 255 | 64 | 128 | 49,856 | - -### License - -All included code has been placed into -[Public Domain](LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt) -and is available under various open source licenses -([Creative Commons Zero v1.0 Universal (CC0-1.0)](LICENSES/CC0-1.0.txt), -[BSD Zero Clause License (0BSD)](LICENSES/0BSD.txt), and -[MIT No Attribution (MIT-0)](LICENSES/MIT-0.txt), -see the [LICENSE file](LICENSE) and the licenses in the [LICENSES folder](LICENSES)), with the exception of `rng.c`, `rng.h` and `PQCgenKAT_sign.c`, which were provided by NIST, and parts of `ref/haraka.c`, which are under -[MIT license (MIT)](LICENSES/MIT.txt). - -[test-ref]: https://github.com/sphincs/sphincsplus/actions/workflows/test-ref.yml/badge.svg -[test-sha256-avx2]: https://github.com/sphincs/sphincsplus/actions/workflows/test-sha256-avx2.yml/badge.svg -[test-shake256-avx2]: https://github.com/sphincs/sphincsplus/actions/workflows/test-shake256-avx2.yml/badge.svg -[test-haraka-aesni]: https://github.com/sphincs/sphincsplus/actions/workflows/test-haraka-aesni.yml/badge.svg diff --git a/sphincsplus/SHA256SUMS b/sphincsplus/SHA256SUMS deleted file mode 100644 index e781c99..0000000 --- a/sphincsplus/SHA256SUMS +++ /dev/null @@ -1,36 +0,0 @@ -9e1b3168520c917b6de676caa7a5799ec972e55caa150090e8452c80c299545e sphincs-haraka-128f-robust -c6a28dcf0667bd91c7bb46814ac7408c0375727fe5fec7d41332149006d3f9d7 sphincs-haraka-128f-simple -f93f4a554322080545a70f85ce936a12acc2fe928a243e3d13546ffe87872a9e sphincs-haraka-128s-robust -3c9b181d3d96c066039b77e9accd926745fe1ecb010039d3579140b877da6f33 sphincs-haraka-128s-simple -8876bfae8924983db27acfeaee6252d37cea86f05fcc4b16ea2c902d717e6a6e sphincs-haraka-192f-robust -df26bd02796f5ad9d6ff412793960e79ec911cbf4521656814895e6ef5a1db83 sphincs-haraka-192f-simple -6cfde6cb5f9ce93eb3f7b0845e1149f661f92000f54e9d340c0bff504920ec7e sphincs-haraka-192s-robust -64037177e1524f2b2d3ea4a79fdaf9352eb39a3aa6e68bc9d3316b7c2b835820 sphincs-haraka-192s-simple -a838509fa6ec49ade2638efc35d9e29fdb56bd9b843d5e1f48210a2cab218332 sphincs-haraka-256f-robust -e1e3258be6b4467bcea81392363f657a58278a5b99fe240f29e388b0fe72f5da sphincs-haraka-256f-simple -b5c5cc535f03789c25c018c009615ac62ba5b64188e4db5e3ede5513e3704dcc sphincs-haraka-256s-robust -9428a566a2c2ee03665fc0eb2dbf208deb1b28716dc8c2d5e7c036a9f83d31da sphincs-haraka-256s-simple -b6c82007bbce794f9fd67de708cd4d959319c744b918ddb28795fd491b713aa9 sphincs-sha2-128f-robust -708f6ab77f8026361e975f7be7b9b5d1cd8aca56e4a3604c85ef3f9fe6618549 sphincs-sha2-128f-simple -f4c2f31082fc8ad15419edc4f24c34a83d909f75eb37ea5ffe53df0fb5ef5306 sphincs-sha2-128s-robust -65942fac8e225fde77dd277d297e68c94c2e25a2a4089f88be4b56fa92b18a84 sphincs-sha2-128s-simple -b8e617db2099e617dfc372ff732eead88872aea791e2fe82628568d75dd03c78 sphincs-sha2-192f-robust -84b1a342683bcad658efb6c65f7367c6b30623e74e3a24c2238d19eaf74722ab sphincs-sha2-192f-simple -50c4b94dc788446077b48af1d8fa0170dc2114b4cb72a19f1d8c7628f9dadfd6 sphincs-sha2-192s-robust -13efa67b9297afa051b9b30e2686266350c8b4000caa49aa432516e2a86d0b68 sphincs-sha2-192s-simple -dc3330f8f19c816f45ee9a1127bf2b8a8c900e05df9a964bb760f0adf8f9b1b3 sphincs-sha2-256f-robust -46e286dc1a20012789c1bf4793a8eb2043dd0c11df729fa36d9f96b0aeffdac6 sphincs-sha2-256f-simple -1f42b407e1e351861ba23e520b1974f399e349fcb66c614d727a38fb4e646634 sphincs-sha2-256s-robust -c816ca365a667e4d6564a95ac576bc9d7be0de7e66eff93e6f05dd4f134a183f sphincs-sha2-256s-simple -4be71430814589ce7c861030c7cdce0aa73f75885b693b41fdb7c34d8f32fa79 sphincs-shake-128f-robust -5167df2ce46f33b76ccf0688f7769217d91878bd7d9b431080a3032eba51da10 sphincs-shake-128f-simple -fbe6c99d6ccc42fc9af5babbac532f28288d4164b182515dffeb1cd47f351d12 sphincs-shake-128s-robust -e7d5caee1941be99b6dfe46a95fc4535a34792f429e61d1cdc7fd3bbafe9ff02 sphincs-shake-128s-simple -243d0e25de08fea547b0beae5f778a48bd55e56066435f9cdb9afc60a722699e sphincs-shake-192f-robust -f204fd1cd5dce187441d104ae7159b64322b6a4afae708d48dc9966fe418ec4e sphincs-shake-192f-simple -cb13eaa2b1c074f53c87f1025e6bb1b356ad8de3bea9388b90a058a6460766bb sphincs-shake-192s-robust -4cc01c4a562d738ac54f5abfead35ecc4f46a1e2531fa12b4bc2819f4560c351 sphincs-shake-192s-simple -5a736aeba47f8d84e3ca47126715affcb4ce6cef13e3c9f6af220827973aa383 sphincs-shake-256f-robust -127f7ab83c740344546fe30777b221e8cb39f30fc4242d07d7608dc31a9835d4 sphincs-shake-256f-simple -4d2ca7d10f2206c3cb9a26c6b00a0361601a1fe2dddf102fbfd6d3dac0be10fe sphincs-shake-256s-robust -4ce4552e2e9b009a9016eb6dbcbefae3da2de151d61e2f392d4b9517eaeab91d sphincs-shake-256s-simple diff --git a/sphincsplus/benchmark.py b/sphincsplus/benchmark.py deleted file mode 100755 index 4ae6003..0000000 --- a/sphincsplus/benchmark.py +++ /dev/null @@ -1,39 +0,0 @@ -#! /usr/bin/env python3 -import fileinput -import itertools -import os -import sys -from subprocess import DEVNULL, run - -implementations = [ - ('ref', ['shake', 'sha2', 'haraka']), - ('haraka-aesni', ['haraka']), - ('shake-avx2', ['shake']), - ('sha2-avx2', ['sha2']), - ] - -options = ["f", "s"] -sizes = [128, 192, 256] -thashes = ['robust', 'simple'] - -for impl, fns in implementations: - params = os.path.join(impl, "params.h") - for fn in fns: - for opt, size, thash in itertools.product(options, sizes, thashes): - paramset = "sphincs-{}-{}{}".format(fn, size, opt) - paramfile = "params-{}.h".format(paramset) - - print("Benchmarking", paramset, thash, "using", impl, flush=True) - - params = 'PARAMS={}'.format(paramset) # overrides Makefile var - thash = 'THASH={}'.format(thash) # overrides Makefile var - - run(["make", "-C", impl, "clean", thash, params], - stdout=DEVNULL, stderr=sys.stderr) - run(["make", "-C", impl, "benchmarks", thash, params], - stdout=DEVNULL, stderr=sys.stderr) - run(["make", "-C", impl, "benchmark", thash, params], - stdout=sys.stdout, stderr=sys.stderr) - - print(flush=True) - diff --git a/sphincsplus/haraka-aesni/.gitignore b/sphincsplus/haraka-aesni/.gitignore deleted file mode 100644 index 67bcef9..0000000 --- a/sphincsplus/haraka-aesni/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -test/* -!test/*.c -PQCsignKAT_*.rsp -PQCsignKAT_*.req -PQCgenKAT_sign diff --git a/sphincsplus/haraka-aesni/Makefile b/sphincsplus/haraka-aesni/Makefile deleted file mode 100644 index a5c5816..0000000 --- a/sphincsplus/haraka-aesni/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -PARAMS = sphincs-haraka-128f -THASH = robust - -CC = /usr/bin/gcc -CFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3 -std=c99 -march=native -fomit-frame-pointer -flto -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) - - -SOURCES = hash_haraka.c hash_harakax4.c thash_haraka_$(THASH).c thash_haraka_$(THASH)x4.c address.c randombytes.c merkle.c wots.c utils.c utilsx4.c fors.c sign.c haraka.c -HEADERS = params.h hash.h hashx4.h thash.h thashx4.h address.h randombytes.h merkle.c wots.h utils.h utilsx4.h fors.h api.h haraka.h harakax4.h - -DET_SOURCES = $(SOURCES:randombytes.%=rng.%) -DET_HEADERS = $(HEADERS:randombytes.%=rng.%) - -TESTS = test/fors \ - test/spx \ - -BENCHMARK = test/benchmark - -.PHONY: clean test benchmark - -default: PQCgenKAT_sign - -all: PQCgenKAT_sign tests benchmarks - -tests: $(TESTS) - -test: $(TESTS:=.exec) - -benchmarks: $(BENCHMARK) - -benchmark: $(BENCHMARK:=.exec) - -PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) - $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto - -test/%: test/%.c $(SOURCES) $(HEADERS) - $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) - -test/%.exec: test/% - @$< - -clean: - -$(RM) $(TESTS) - -$(RM) $(BENCHMARK) - -$(RM) PQCgenKAT_sign - -$(RM) PQCsignKAT_*.rsp - -$(RM) PQCsignKAT_*.req diff --git a/sphincsplus/haraka-aesni/PQCgenKAT_sign.c b/sphincsplus/haraka-aesni/PQCgenKAT_sign.c deleted file mode 120000 index a17dbe2..0000000 --- a/sphincsplus/haraka-aesni/PQCgenKAT_sign.c +++ /dev/null @@ -1 +0,0 @@ -../ref/PQCgenKAT_sign.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/address.c b/sphincsplus/haraka-aesni/address.c deleted file mode 120000 index 02c52c6..0000000 --- a/sphincsplus/haraka-aesni/address.c +++ /dev/null @@ -1 +0,0 @@ -../ref/address.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/address.h b/sphincsplus/haraka-aesni/address.h deleted file mode 120000 index e670da5..0000000 --- a/sphincsplus/haraka-aesni/address.h +++ /dev/null @@ -1 +0,0 @@ -../ref/address.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/api.h b/sphincsplus/haraka-aesni/api.h deleted file mode 120000 index ea89e0a..0000000 --- a/sphincsplus/haraka-aesni/api.h +++ /dev/null @@ -1 +0,0 @@ -../ref/api.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/context.h b/sphincsplus/haraka-aesni/context.h deleted file mode 100644 index f88445a..0000000 --- a/sphincsplus/haraka-aesni/context.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" -#include "immintrin.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#endif diff --git a/sphincsplus/haraka-aesni/fors.c b/sphincsplus/haraka-aesni/fors.c deleted file mode 120000 index abd8d52..0000000 --- a/sphincsplus/haraka-aesni/fors.c +++ /dev/null @@ -1 +0,0 @@ -../shake-avx2/fors.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/fors.h b/sphincsplus/haraka-aesni/fors.h deleted file mode 120000 index 07156bd..0000000 --- a/sphincsplus/haraka-aesni/fors.h +++ /dev/null @@ -1 +0,0 @@ -../ref/fors.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/haraka.c b/sphincsplus/haraka-aesni/haraka.c deleted file mode 100644 index 2d01db8..0000000 --- a/sphincsplus/haraka-aesni/haraka.c +++ /dev/null @@ -1,720 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - s1 = _mm_aesenc_si128(s1, *(rci + 1)); \ - s0 = _mm_aesenc_si128(s0, *(rci + 2)); \ - s1 = _mm_aesenc_si128(s1, *(rci + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2(s0[0], s0[1], rci); \ - AES2(s1[0], s1[1], rci); \ - AES2(s2[0], s2[1], rci); \ - AES2(s3[0], s3[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - s1 = _mm_aesenc_si128(s1, *(rci + 1)); \ - s2 = _mm_aesenc_si128(s2, *(rci + 2)); \ - s3 = _mm_aesenc_si128(s3, *(rci + 3)); \ - s0 = _mm_aesenc_si128(s0, *(rci + 4)); \ - s1 = _mm_aesenc_si128(s1, *(rci + 5)); \ - s2 = _mm_aesenc_si128(s2, *(rci + 6)); \ - s3 = _mm_aesenc_si128(s3, *(rci + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4(s0[0], s0[1], s0[2], s0[3], rci); \ - AES4(s1[0], s1[1], s1[2], s1[3], rci); \ - AES4(s2[0], s2[1], s2[2], s2[3], rci); \ - AES4(s3[0], s3[1], s3[2], s3[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - s1 = _mm_unpackhi_epi32(s0, s1); \ - s0 = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - s0 = _mm_unpackhi_epi32(s0, s1); \ - s1 = _mm_unpacklo_epi32(s2, s3); \ - s2 = _mm_unpackhi_epi32(s2, s3); \ - s3 = _mm_unpacklo_epi32(s0, s2); \ - s0 = _mm_unpackhi_epi32(s0, s2); \ - s2 = _mm_unpackhi_epi32(s1, tmp); \ - s1 = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)out, \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)(out + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) -{ - rc[0] = _mm_set_epi32(0x0684704c,0xe620c00a,0xb2c5fef0,0x75817b9d); - rc[1] = _mm_set_epi32(0x8b66b4e1,0x88f3a06b,0x640f6ba4,0x2f08f717); - rc[2] = _mm_set_epi32(0x3402de2d,0x53f28498,0xcf029d60,0x9f029114); - rc[3] = _mm_set_epi32(0x0ed6eae6,0x2e7b4f08,0xbbf3bcaf,0xfd5b4f79); - rc[4] = _mm_set_epi32(0xcbcfb0cb,0x4872448b,0x79eecd1c,0xbe397044); - rc[5] = _mm_set_epi32(0x7eeacdee,0x6e9032b7,0x8d5335ed,0x2b8a057b); - rc[6] = _mm_set_epi32(0x67c28f43,0x5e2e7cd0,0xe2412761,0xda4fef1b); - rc[7] = _mm_set_epi32(0x2924d9b0,0xafcacc07,0x675ffde2,0x1fc70b3b); - rc[8] = _mm_set_epi32(0xab4d63f1,0xe6867fe9,0xecdb8fca,0xb9d465ee); - rc[9] = _mm_set_epi32(0x1c30bf84,0xd4b7cd64,0x5b2a404f,0xad037e33); - rc[10] = _mm_set_epi32(0xb2cc0bb9,0x941723bf,0x69028b2e,0x8df69800); - rc[11] = _mm_set_epi32(0xfa0478a6,0xde6f5572,0x4aaa9ec8,0x5c9d2d8a); - rc[12] = _mm_set_epi32(0xdfb49f2b,0x6b772a12,0x0efa4f2e,0x29129fd4); - rc[13] = _mm_set_epi32(0x1ea10344,0xf449a236,0x32d611ae,0xbb6a12ee); - rc[14] = _mm_set_epi32(0xaf044988,0x4b050084,0x5f9600c9,0x9ca8eca6); - rc[15] = _mm_set_epi32(0x21025ed8,0x9d199c4f,0x78a2c7e3,0x27e593ec); - rc[16] = _mm_set_epi32(0xbf3aaaf8,0xa759c9b7,0xb9282ecd,0x82d40173); - rc[17] = _mm_set_epi32(0x6260700d,0x6186b017,0x37f2efd9,0x10307d6b); - rc[18] = _mm_set_epi32(0x5aca45c2,0x21300443,0x81c29153,0xf6fc9ac6); - rc[19] = _mm_set_epi32(0x9223973c,0x226b68bb,0x2caf92e8,0x36d1943a); - rc[20] = _mm_set_epi32(0xd3bf9238,0x225886eb,0x6cbab958,0xe51071b4); - rc[21] = _mm_set_epi32(0xdb863ce5,0xaef0c677,0x933dfddd,0x24e1128d); - rc[22] = _mm_set_epi32(0xbb606268,0xffeba09c,0x83e48de3,0xcb2212b1); - rc[23] = _mm_set_epi32(0x734bd3dc,0xe2e4d19c,0x2db91a4e,0xc72bf77d); - rc[24] = _mm_set_epi32(0x43bb47c3,0x61301b43,0x4b1415c4,0x2cb3924e); - rc[25] = _mm_set_epi32(0xdba775a8,0xe707eff6,0x03b231dd,0x16eb6899); - rc[26] = _mm_set_epi32(0x6df3614b,0x3c755977,0x8e5e2302,0x7eca472c); - rc[27] = _mm_set_epi32(0xcda75a17,0xd6de7d77,0x6d1be5b9,0xb88617f9); - rc[28] = _mm_set_epi32(0xec6b43f0,0x6ba8e9aa,0x9d6c069d,0xa946ee5d); - rc[29] = _mm_set_epi32(0xcb1e6950,0xf957332b,0xa2531159,0x3bf327c1); - rc[30] = _mm_set_epi32(0x2cee0c75,0x00da619c,0xe4ed0353,0x600ed0d9); - rc[31] = _mm_set_epi32(0xf0b1a5a1,0x96e90cab,0x80bbbabc,0x63a4a350); - rc[32] = _mm_set_epi32(0xae3db102,0x5e962988,0xab0dde30,0x938dca39); - rc[33] = _mm_set_epi32(0x17bb8f38,0xd554a40b,0x8814f3a8,0x2e75b442); - rc[34] = _mm_set_epi32(0x34bb8a5b,0x5f427fd7,0xaeb6b779,0x360a16f6); - rc[35] = _mm_set_epi32(0x26f65241,0xcbe55438,0x43ce5918,0xffbaafde); - rc[36] = _mm_set_epi32(0x4ce99a54,0xb9f3026a,0xa2ca9cf7,0x839ec978); - rc[37] = _mm_set_epi32(0xae51a51a,0x1bdff7be,0x40c06e28,0x22901235); - rc[38] = _mm_set_epi32(0xa0c1613c,0xba7ed22b,0xc173bc0f,0x48a659cf); - rc[39] = _mm_set_epi32(0x756acc03,0x02288288,0x4ad6bdfd,0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) -{ - int i; - unsigned char buf[40*16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40*16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i*16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) -{ - unsigned long long i; - SPX_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - mlen -= r; - m += r; - } - - for (i = 0; i < r; ++i) { - t[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t[i] = m[i]; - } - t[i] = p; - t[r - 1] |= 128; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) -{ - unsigned long long i; - SPX_VLA(unsigned char, t0, r); - SPX_VLA(unsigned char, t1, r); - SPX_VLA(unsigned char, t2, r); - SPX_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) -{ - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) -{ - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) -{ - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) -{ - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) -{ - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) -{ - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = HARAKAS_RATE - i; - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) -{ - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) -{ - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) -{ - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) -{ - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) -{ - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) -{ - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) -{ - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) -{ - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/sphincsplus/haraka-aesni/haraka.h b/sphincsplus/haraka-aesni/haraka.h deleted file mode 120000 index 0378b1e..0000000 --- a/sphincsplus/haraka-aesni/haraka.h +++ /dev/null @@ -1 +0,0 @@ -../ref/haraka.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/haraka_offsets.h b/sphincsplus/haraka-aesni/haraka_offsets.h deleted file mode 120000 index cb6abf9..0000000 --- a/sphincsplus/haraka-aesni/haraka_offsets.h +++ /dev/null @@ -1 +0,0 @@ -../ref/haraka_offsets.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/harakax4.h b/sphincsplus/haraka-aesni/harakax4.h deleted file mode 100644 index 2a18650..0000000 --- a/sphincsplus/haraka-aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/sphincsplus/haraka-aesni/hash.h b/sphincsplus/haraka-aesni/hash.h deleted file mode 120000 index cffc52b..0000000 --- a/sphincsplus/haraka-aesni/hash.h +++ /dev/null @@ -1 +0,0 @@ -../ref/hash.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/hash_haraka.c b/sphincsplus/haraka-aesni/hash_haraka.c deleted file mode 120000 index 6c5febe..0000000 --- a/sphincsplus/haraka-aesni/hash_haraka.c +++ /dev/null @@ -1 +0,0 @@ -../ref/hash_haraka.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/hash_harakax4.c b/sphincsplus/haraka-aesni/hash_harakax4.c deleted file mode 100644 index e970078..0000000 --- a/sphincsplus/haraka-aesni/hash_harakax4.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "harakax4.h" -#include "hashx4.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4*8]) -{ - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i*64, addrx4 + i*8, SPX_ADDR_BYTES); - memcpy(bufx4 + i*64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/sphincsplus/haraka-aesni/hashx4.h b/sphincsplus/haraka-aesni/hashx4.h deleted file mode 120000 index 3dc1ba4..0000000 --- a/sphincsplus/haraka-aesni/hashx4.h +++ /dev/null @@ -1 +0,0 @@ -../shake-avx2/hashx4.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/merkle.c b/sphincsplus/haraka-aesni/merkle.c deleted file mode 120000 index 7a8454d..0000000 --- a/sphincsplus/haraka-aesni/merkle.c +++ /dev/null @@ -1 +0,0 @@ -../shake-avx2/merkle.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/merkle.h b/sphincsplus/haraka-aesni/merkle.h deleted file mode 120000 index 7d167ed..0000000 --- a/sphincsplus/haraka-aesni/merkle.h +++ /dev/null @@ -1 +0,0 @@ -../ref/merkle.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/params.h b/sphincsplus/haraka-aesni/params.h deleted file mode 120000 index 53133cc..0000000 --- a/sphincsplus/haraka-aesni/params.h +++ /dev/null @@ -1 +0,0 @@ -../ref/params.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-128f.h b/sphincsplus/haraka-aesni/params/params-sphincs-haraka-128f.h deleted file mode 120000 index 4e5417f..0000000 --- a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-128f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-haraka-128f.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-128s.h b/sphincsplus/haraka-aesni/params/params-sphincs-haraka-128s.h deleted file mode 120000 index 686aa8c..0000000 --- a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-128s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-haraka-128s.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-192f.h b/sphincsplus/haraka-aesni/params/params-sphincs-haraka-192f.h deleted file mode 120000 index 14971bf..0000000 --- a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-192f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-haraka-192f.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-192s.h b/sphincsplus/haraka-aesni/params/params-sphincs-haraka-192s.h deleted file mode 120000 index 3361225..0000000 --- a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-192s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-haraka-192s.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-256f.h b/sphincsplus/haraka-aesni/params/params-sphincs-haraka-256f.h deleted file mode 120000 index 28d6862..0000000 --- a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-256f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-haraka-256f.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-256s.h b/sphincsplus/haraka-aesni/params/params-sphincs-haraka-256s.h deleted file mode 120000 index 233ce46..0000000 --- a/sphincsplus/haraka-aesni/params/params-sphincs-haraka-256s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-haraka-256s.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/randombytes.c b/sphincsplus/haraka-aesni/randombytes.c deleted file mode 120000 index 59a42a5..0000000 --- a/sphincsplus/haraka-aesni/randombytes.c +++ /dev/null @@ -1 +0,0 @@ -../ref/randombytes.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/randombytes.h b/sphincsplus/haraka-aesni/randombytes.h deleted file mode 120000 index 055e443..0000000 --- a/sphincsplus/haraka-aesni/randombytes.h +++ /dev/null @@ -1 +0,0 @@ -../ref/randombytes.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/rng.c b/sphincsplus/haraka-aesni/rng.c deleted file mode 120000 index 6e2fdac..0000000 --- a/sphincsplus/haraka-aesni/rng.c +++ /dev/null @@ -1 +0,0 @@ -../ref/rng.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/rng.h b/sphincsplus/haraka-aesni/rng.h deleted file mode 120000 index d678c7c..0000000 --- a/sphincsplus/haraka-aesni/rng.h +++ /dev/null @@ -1 +0,0 @@ -../ref/rng.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/sign.c b/sphincsplus/haraka-aesni/sign.c deleted file mode 120000 index 42fea88..0000000 --- a/sphincsplus/haraka-aesni/sign.c +++ /dev/null @@ -1 +0,0 @@ -../ref/sign.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/test/benchmark.c b/sphincsplus/haraka-aesni/test/benchmark.c deleted file mode 100644 index 1c87297..0000000 --- a/sphincsplus/haraka-aesni/test/benchmark.c +++ /dev/null @@ -1,162 +0,0 @@ -#define _POSIX_C_SOURCE 199309L - -#include -#include -#include - -#include "../api.h" -#include "../fors.h" -#include "../wotsx4.h" -#include "../params.h" -#include "../randombytes.h" - -#define SPX_MLEN 32 -#define NTESTS 10 - -static void wots_gen_pkx4(unsigned char* pk, const spx_ctx *ctx, - uint32_t addr[8]); - -static int cmp_llu(const void *a, const void*b) -{ - if(*(unsigned long long *)a < *(unsigned long long *)b) return -1; - if(*(unsigned long long *)a > *(unsigned long long *)b) return 1; - return 0; -} - -static unsigned long long median(unsigned long long *l, size_t llen) -{ - qsort(l,llen,sizeof(unsigned long long),cmp_llu); - - if(llen%2) return l[llen/2]; - else return (l[llen/2-1]+l[llen/2])/2; -} - -static void delta(unsigned long long *l, size_t llen) -{ - unsigned int i; - for(i = 0; i < llen - 1; i++) { - l[i] = l[i+1] - l[i]; - } -} - -static unsigned long long cpucycles(void) -{ - unsigned long long result; - __asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax" - : "=a" (result) :: "%rdx"); - return result; -} - -static void printfcomma (unsigned long long n) -{ - if (n < 1000) { - printf("%llu", n); - return; - } - printfcomma(n / 1000); - printf (",%03llu", n % 1000); -} - -static void printfalignedcomma (unsigned long long n, int len) -{ - unsigned long long ncopy = n; - int i = 0; - - while (ncopy > 9) { - len -= 1; - ncopy /= 10; - i += 1; // to account for commas - } - i = i/3 - 1; // to account for commas - for (; i < len; i++) { - printf(" "); - } - printfcomma(n); -} - -static void display_result(double result, unsigned long long *l, size_t llen, unsigned long long mul) -{ - unsigned long long med; - - result /= NTESTS; - delta(l, NTESTS + 1); - med = median(l, llen); - printf("avg. %11.2lf us (%2.2lf sec); median ", result, result / 1e6); - printfalignedcomma(med, 12); - printf(" cycles, %5llux: ", mul); - printfalignedcomma(mul*med, 12); - printf(" cycles\n"); -} - -#define MEASURE(TEXT, MUL, FNCALL)\ - printf(TEXT);\ - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);\ - for(i = 0; i < NTESTS; i++) {\ - t[i] = cpucycles();\ - FNCALL;\ - }\ - t[NTESTS] = cpucycles();\ - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop);\ - result = (stop.tv_sec - start.tv_sec) * 1e6 + (stop.tv_nsec - start.tv_nsec) / 1e3;\ - display_result(result, t, NTESTS, MUL); - -int main(void) -{ - /* Make stdout buffer more responsive. */ - setbuf(stdout, NULL); - - spx_ctx ctx; - unsigned char pk[SPX_PK_BYTES]; - unsigned char sk[SPX_SK_BYTES]; - unsigned char *m = malloc(SPX_MLEN); - unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); - unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); - - unsigned char fors_pk[SPX_FORS_PK_BYTES]; - unsigned char fors_m[SPX_FORS_MSG_BYTES]; - unsigned char fors_sig[SPX_FORS_BYTES]; - unsigned char addr[SPX_ADDR_BYTES]; - - unsigned char wots_pk[SPX_WOTS_PK_BYTES]; - - unsigned long long smlen; - unsigned long long mlen; - unsigned long long t[NTESTS+1]; - struct timespec start, stop; - double result; - int i; - - randombytes(m, SPX_MLEN); - randombytes(addr, SPX_ADDR_BYTES); - - printf("Parameters: n = %d, h = %d, d = %d, b = %d, k = %d, w = %d\n", - SPX_N, SPX_FULL_HEIGHT, SPX_D, SPX_FORS_HEIGHT, SPX_FORS_TREES, - SPX_WOTS_W); - - printf("Running %d iterations.\n", NTESTS); - - MEASURE("Generating keypair.. ", 1, crypto_sign_keypair(pk, sk)); - MEASURE(" - WOTS pk gen.. ", (1 << SPX_TREE_HEIGHT), wots_gen_pkx4(wots_pk, &ctx, (uint32_t *) addr)); - MEASURE("Signing.. ", 1, crypto_sign(sm, &smlen, m, SPX_MLEN, sk)); - MEASURE(" - FORS signing.. ", 1, fors_sign(fors_sig, fors_pk, fors_m, &ctx, (uint32_t *) addr)); - MEASURE(" - WOTS pk gen.. ", SPX_D * (1 << SPX_TREE_HEIGHT), wots_gen_pkx4(wots_pk, &ctx, (uint32_t *) addr)); - MEASURE("Verifying.. ", 1, crypto_sign_open(mout, &mlen, sm, smlen, pk)); - - printf("Signature size: %d (%.2f KiB)\n", SPX_BYTES, SPX_BYTES / 1024.0); - printf("Public key size: %d (%.2f KiB)\n", SPX_PK_BYTES, SPX_PK_BYTES / 1024.0); - printf("Secret key size: %d (%.2f KiB)\n", SPX_SK_BYTES, SPX_SK_BYTES / 1024.0); - - free(m); - free(sm); - free(mout); - - return 0; -} - -static void wots_gen_pkx4(unsigned char *pk, const spx_ctx *ctx, - uint32_t addr[8]) { - struct leaf_info_x4 leaf; - unsigned steps[ SPX_WOTS_LEN ] = { 0 }; - INITIALIZE_LEAF_INFO_X4(leaf, addr, steps); - wots_gen_leafx4(pk, ctx, 0, &leaf); -} diff --git a/sphincsplus/haraka-aesni/test/fors.c b/sphincsplus/haraka-aesni/test/fors.c deleted file mode 120000 index b2bccee..0000000 --- a/sphincsplus/haraka-aesni/test/fors.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/fors.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/test/spx.c b/sphincsplus/haraka-aesni/test/spx.c deleted file mode 120000 index 7af26df..0000000 --- a/sphincsplus/haraka-aesni/test/spx.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/spx.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/thash.h b/sphincsplus/haraka-aesni/thash.h deleted file mode 120000 index 937dd48..0000000 --- a/sphincsplus/haraka-aesni/thash.h +++ /dev/null @@ -1 +0,0 @@ -../ref/thash.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/thash_haraka_robust.c b/sphincsplus/haraka-aesni/thash_haraka_robust.c deleted file mode 120000 index 156c18d..0000000 --- a/sphincsplus/haraka-aesni/thash_haraka_robust.c +++ /dev/null @@ -1 +0,0 @@ -../ref/thash_haraka_robust.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/thash_haraka_robustx4.c b/sphincsplus/haraka-aesni/thash_haraka_robustx4.c deleted file mode 100644 index 15d19f1..0000000 --- a/sphincsplus/haraka-aesni/thash_haraka_robustx4.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include "thashx4.h" -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "harakax4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4*8]) -{ - SPX_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, bitmask0, inblocks * SPX_N); - SPX_VLA(unsigned char, bitmask1, inblocks * SPX_N); - SPX_VLA(unsigned char, bitmask2, inblocks * SPX_N); - SPX_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - unsigned int i; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - // Generate masks first in buffer - memcpy(buf_tmp, addrx4 + 0*8, 32); - memcpy(buf_tmp + 32, addrx4 + 1*8, 32); - memcpy(buf_tmp + 64, addrx4 + 2*8, 32); - memcpy(buf_tmp + 96, addrx4 + 3*8, 32); - - haraka256x4(outbuf, buf_tmp, ctx); - - /* move addresses to make room for inputs; zero old values */ - memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); - memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); - memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); - /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ - - /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ - memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); - /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ - memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); - - for (i = 0; i < SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; - buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; - buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; - buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; - } - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0*8, 32); - memcpy(buf1, addrx4 + 1*8, 32); - memcpy(buf2, addrx4 + 2*8, 32); - memcpy(buf3, addrx4 + 3*8, 32); - - haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks*SPX_N, - ctx); - } -} diff --git a/sphincsplus/haraka-aesni/thash_haraka_simple.c b/sphincsplus/haraka-aesni/thash_haraka_simple.c deleted file mode 120000 index 4d3c767..0000000 --- a/sphincsplus/haraka-aesni/thash_haraka_simple.c +++ /dev/null @@ -1 +0,0 @@ -../ref/thash_haraka_simple.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/thash_haraka_simplex4.c b/sphincsplus/haraka-aesni/thash_haraka_simplex4.c deleted file mode 100644 index 841d445..0000000 --- a/sphincsplus/haraka-aesni/thash_haraka_simplex4.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include "thashx4.h" -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "harakax4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4*8]) -{ - SPX_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks*SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - memcpy(buf_tmp, addrx4 + 0*8, 32); - memcpy(buf_tmp + 64, addrx4 + 1*8, 32); - memcpy(buf_tmp + 128, addrx4 + 2*8, 32); - memcpy(buf_tmp + 192, addrx4 + 3*8, 32); - - memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0*8, 32); - memcpy(buf1, addrx4 + 1*8, 32); - memcpy(buf2, addrx4 + 2*8, 32); - memcpy(buf3, addrx4 + 3*8, 32); - - memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); - memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); - memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); - memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks*SPX_N, - ctx); - } -} diff --git a/sphincsplus/haraka-aesni/thashx4.h b/sphincsplus/haraka-aesni/thashx4.h deleted file mode 120000 index 982555e..0000000 --- a/sphincsplus/haraka-aesni/thashx4.h +++ /dev/null @@ -1 +0,0 @@ -../shake-avx2/thashx4.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/utils.c b/sphincsplus/haraka-aesni/utils.c deleted file mode 120000 index e8ef6eb..0000000 --- a/sphincsplus/haraka-aesni/utils.c +++ /dev/null @@ -1 +0,0 @@ -../ref/utils.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/utils.h b/sphincsplus/haraka-aesni/utils.h deleted file mode 120000 index 51b0d39..0000000 --- a/sphincsplus/haraka-aesni/utils.h +++ /dev/null @@ -1 +0,0 @@ -../ref/utils.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/utilsx4.c b/sphincsplus/haraka-aesni/utilsx4.c deleted file mode 120000 index ea6a5cf..0000000 --- a/sphincsplus/haraka-aesni/utilsx4.c +++ /dev/null @@ -1 +0,0 @@ -../shake-avx2/utilsx4.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/utilsx4.h b/sphincsplus/haraka-aesni/utilsx4.h deleted file mode 120000 index faf4c28..0000000 --- a/sphincsplus/haraka-aesni/utilsx4.h +++ /dev/null @@ -1 +0,0 @@ -../shake-avx2/utilsx4.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/wots.c b/sphincsplus/haraka-aesni/wots.c deleted file mode 120000 index 07845f1..0000000 --- a/sphincsplus/haraka-aesni/wots.c +++ /dev/null @@ -1 +0,0 @@ -../shake-avx2/wots.c \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/wots.h b/sphincsplus/haraka-aesni/wots.h deleted file mode 120000 index 8c327ea..0000000 --- a/sphincsplus/haraka-aesni/wots.h +++ /dev/null @@ -1 +0,0 @@ -../ref/wots.h \ No newline at end of file diff --git a/sphincsplus/haraka-aesni/wotsx4.h b/sphincsplus/haraka-aesni/wotsx4.h deleted file mode 120000 index db76d0f..0000000 --- a/sphincsplus/haraka-aesni/wotsx4.h +++ /dev/null @@ -1 +0,0 @@ -../shake-avx2/wotsx4.h \ No newline at end of file diff --git a/sphincsplus/ref/.gitignore b/sphincsplus/ref/.gitignore deleted file mode 100644 index 67bcef9..0000000 --- a/sphincsplus/ref/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -test/* -!test/*.c -PQCsignKAT_*.rsp -PQCsignKAT_*.req -PQCgenKAT_sign diff --git a/sphincsplus/ref/Makefile b/sphincsplus/ref/Makefile deleted file mode 100644 index a3aabad..0000000 --- a/sphincsplus/ref/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -PARAMS = sphincs-haraka-128f -THASH = robust - -CC=/usr/bin/gcc -CFLAGS=-Wall -Wextra -Wpedantic -O3 -std=c99 -Wconversion -Wmissing-prototypes -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) - -SOURCES = address.c randombytes.c merkle.c wots.c wotsx1.c utils.c utilsx1.c fors.c sign.c -HEADERS = params.h address.h randombytes.h merkle.h wots.h wotsx1.h utils.h utilsx1.h fors.h api.h hash.h thash.h - -ifneq (,$(findstring shake,$(PARAMS))) - SOURCES += fips202.c hash_shake.c thash_shake_$(THASH).c - HEADERS += fips202.h -endif -ifneq (,$(findstring haraka,$(PARAMS))) - SOURCES += haraka.c hash_haraka.c thash_haraka_$(THASH).c - HEADERS += haraka.h -endif -ifneq (,$(findstring sha2,$(PARAMS))) - SOURCES += sha2.c hash_sha2.c thash_sha2_$(THASH).c - HEADERS += sha2.h -endif - -DET_SOURCES = $(SOURCES:randombytes.%=rng.%) -DET_HEADERS = $(HEADERS:randombytes.%=rng.%) - -TESTS = test/fors \ - test/spx \ - -BENCHMARK = test/benchmark - -.PHONY: clean test benchmark - -default: PQCgenKAT_sign - -all: PQCgenKAT_sign tests benchmarks - -tests: $(TESTS) - -test: $(TESTS:=.exec) - -benchmarks: $(BENCHMARK) - -benchmark: $(BENCHMARK:=.exec) - -PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) - $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto - -test/benchmark: test/benchmark.c test/cycles.c $(SOURCES) $(HEADERS) - $(CC) $(CFLAGS) -o $@ test/cycles.c $(SOURCES) $< $(LDLIBS) - -test/%: test/%.c $(SOURCES) $(HEADERS) - $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) - -test/haraka: test/haraka.c $(filter-out haraka.c,$(SOURCES)) $(HEADERS) - $(CC) $(CFLAGS) -o $@ $(filter-out haraka.c,$(SOURCES)) $< $(LDLIBS) - -test/%.exec: test/% - @$< - -clean: - -$(RM) $(TESTS) - -$(RM) $(BENCHMARK) - -$(RM) PQCgenKAT_sign - -$(RM) PQCsignKAT_*.rsp - -$(RM) PQCsignKAT_*.req diff --git a/sphincsplus/ref/PQCgenKAT_sign.c b/sphincsplus/ref/PQCgenKAT_sign.c deleted file mode 100644 index 16f41c1..0000000 --- a/sphincsplus/ref/PQCgenKAT_sign.c +++ /dev/null @@ -1,262 +0,0 @@ - -// -// PQCgenKAT_sign.c -// -// Created by Bassham, Lawrence E (Fed) on 8/29/17. -// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. -// -#include -#include -#include -#include -#include "rng.h" -#include "api.h" - -#define MAX_MARKER_LEN 50 - -#define KAT_SUCCESS 0 -#define KAT_FILE_OPEN_ERROR -1 -#define KAT_DATA_ERROR -3 -#define KAT_CRYPTO_FAILURE -4 - -int FindMarker(FILE *infile, const char *marker); -int ReadHex(FILE *infile, unsigned char *A, int Length, char *str); -void fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L); - -char AlgName[] = "My Alg Name"; - -int -main(void) -{ - char fn_req[32], fn_rsp[32]; - FILE *fp_req, *fp_rsp; - unsigned char seed[48]; - unsigned char msg[3300]; - unsigned char entropy_input[48]; - unsigned char *m, *sm, *m1; - unsigned long long mlen, smlen, mlen1; - int count; - int done; - unsigned char pk[CRYPTO_PUBLICKEYBYTES], sk[CRYPTO_SECRETKEYBYTES]; - int ret_val; - - // Create the REQUEST file - sprintf(fn_req, "PQCsignKAT_%d.req", CRYPTO_SECRETKEYBYTES); - if ( (fp_req = fopen(fn_req, "w")) == NULL ) { - printf("Couldn't open <%s> for write\n", fn_req); - return KAT_FILE_OPEN_ERROR; - } - sprintf(fn_rsp, "PQCsignKAT_%d.rsp", CRYPTO_SECRETKEYBYTES); - if ( (fp_rsp = fopen(fn_rsp, "w")) == NULL ) { - printf("Couldn't open <%s> for write\n", fn_rsp); - return KAT_FILE_OPEN_ERROR; - } - - for (int i=0; i<48; i++) - entropy_input[i] = (unsigned char)i; - - randombytes_init(entropy_input, NULL); - for (int i=0; i<100; i++) { - fprintf(fp_req, "count = %d\n", i); - randombytes(seed, 48); - fprintBstr(fp_req, "seed = ", seed, 48); - mlen = (unsigned long long int)(33*(i+1)); - fprintf(fp_req, "mlen = %llu\n", mlen); - randombytes(msg, mlen); - fprintBstr(fp_req, "msg = ", msg, mlen); - fprintf(fp_req, "pk =\n"); - fprintf(fp_req, "sk =\n"); - fprintf(fp_req, "smlen =\n"); - fprintf(fp_req, "sm =\n\n"); - } - fclose(fp_req); - - //Create the RESPONSE file based on what's in the REQUEST file - if ( (fp_req = fopen(fn_req, "r")) == NULL ) { - printf("Couldn't open <%s> for read\n", fn_req); - return KAT_FILE_OPEN_ERROR; - } - - fprintf(fp_rsp, "# %s\n\n", CRYPTO_ALGNAME); - done = 0; - do { - if ( FindMarker(fp_req, "count = ") ) - ret_val = fscanf(fp_req, "%d", &count); - else { - done = 1; - break; - } - fprintf(fp_rsp, "count = %d\n", count); - - if ( !ReadHex(fp_req, seed, 48, "seed = ") ) { - printf("ERROR: unable to read 'seed' from <%s>\n", fn_req); - return KAT_DATA_ERROR; - } - fprintBstr(fp_rsp, "seed = ", seed, 48); - - randombytes_init(seed, NULL); - - if ( FindMarker(fp_req, "mlen = ") ) - ret_val = fscanf(fp_req, "%llu", &mlen); - else { - printf("ERROR: unable to read 'mlen' from <%s>\n", fn_req); - return KAT_DATA_ERROR; - } - fprintf(fp_rsp, "mlen = %llu\n", mlen); - - m = (unsigned char *)calloc(mlen, sizeof(unsigned char)); - m1 = (unsigned char *)calloc(mlen+CRYPTO_BYTES, sizeof(unsigned char)); - sm = (unsigned char *)calloc(mlen+CRYPTO_BYTES, sizeof(unsigned char)); - - if ( !ReadHex(fp_req, m, (int)mlen, "msg = ") ) { - printf("ERROR: unable to read 'msg' from <%s>\n", fn_req); - return KAT_DATA_ERROR; - } - fprintBstr(fp_rsp, "msg = ", m, mlen); - - // Generate the public/private keypair - if ( (ret_val = crypto_sign_keypair(pk, sk)) != 0) { - printf("crypto_sign_keypair returned <%d>\n", ret_val); - return KAT_CRYPTO_FAILURE; - } - fprintBstr(fp_rsp, "pk = ", pk, CRYPTO_PUBLICKEYBYTES); - fprintBstr(fp_rsp, "sk = ", sk, CRYPTO_SECRETKEYBYTES); - - if ( (ret_val = crypto_sign(sm, &smlen, m, mlen, sk)) != 0) { - printf("crypto_sign returned <%d>\n", ret_val); - return KAT_CRYPTO_FAILURE; - } - fprintf(fp_rsp, "smlen = %llu\n", smlen); - fprintBstr(fp_rsp, "sm = ", sm, smlen); - fprintf(fp_rsp, "\n"); - - if ( (ret_val = crypto_sign_open(m1, &mlen1, sm, smlen, pk)) != 0) { - printf("crypto_sign_open returned <%d>\n", ret_val); - return KAT_CRYPTO_FAILURE; - } - - if ( mlen != mlen1 ) { - printf("crypto_sign_open returned bad 'mlen': Got <%llu>, expected <%llu>\n", mlen1, mlen); - return KAT_CRYPTO_FAILURE; - } - - if ( memcmp(m, m1, mlen) ) { - printf("crypto_sign_open returned bad 'm' value\n"); - return KAT_CRYPTO_FAILURE; - } - - free(m); - free(m1); - free(sm); - - } while ( !done ); - - fclose(fp_req); - fclose(fp_rsp); - - return KAT_SUCCESS; -} - -// -// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.) -// -int -FindMarker(FILE *infile, const char *marker) -{ - char line[MAX_MARKER_LEN]; - size_t i, len; - int curr_line; - - len = strlen(marker); - if ( len > MAX_MARKER_LEN-1 ) - len = MAX_MARKER_LEN-1; - - for ( i=0; i= '0') && (ch <= '9') ) - ich = (unsigned char)(ch - '0'); - else if ( (ch >= 'A') && (ch <= 'F') ) - ich = (unsigned char)(ch - 'A' + 10); - else if ( (ch >= 'a') && (ch <= 'f') ) - ich = (unsigned char)(ch - 'a' + 10); - else // shouldn't ever get here - ich = 0; - - for ( i=0; i> 4)); - A[Length-1] = (unsigned char)((A[Length-1] << 4) | ich); - } - else - return 0; - - return 1; -} - -void -fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L) -{ - unsigned long long i; - - fprintf(fp, "%s", S); - - for ( i=0; i -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) -{ - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) -{ -#if (SPX_TREE_HEIGHT * (SPX_D - 1)) > 64 - #error Subtree addressing is currently limited to at most 2^64 trees -#endif - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) -{ - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) -{ - memcpy( out, in, SPX_OFFSET_TREE+8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) -{ - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_KP_ADDR], keypair); -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) -{ - memcpy( out, in, SPX_OFFSET_TREE+8 ); - memcpy( (unsigned char *)out + SPX_OFFSET_KP_ADDR, (unsigned char *)in + SPX_OFFSET_KP_ADDR, 4); -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) -{ - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) -{ - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) -{ - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) -{ - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/sphincsplus/ref/address.h b/sphincsplus/ref/address.h deleted file mode 100644 index 49f8d66..0000000 --- a/sphincsplus/ref/address.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/sphincsplus/ref/api.h b/sphincsplus/ref/api.h deleted file mode 100644 index b89bd52..0000000 --- a/sphincsplus/ref/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME_SPHINCS "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES 3*SPX_N - -/* - * Returns the length of a secret key, in bytes - */ -unsigned long long crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -unsigned long long crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -unsigned long long crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -unsigned long long crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, - const unsigned char *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(unsigned char *sm, unsigned long long *smlen, - const unsigned char *m, unsigned long long mlen, - const unsigned char *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(unsigned char *m, unsigned long long *mlen, - const unsigned char *sm, unsigned long long smlen, - const unsigned char *pk); - -#endif diff --git a/sphincsplus/ref/context.h b/sphincsplus/ref/context.h deleted file mode 100644 index aded564..0000000 --- a/sphincsplus/ref/context.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - -#ifdef SPX_SHA2 - // sha256 state that absorbed pub_seed - uint8_t state_seeded[40]; - -# if SPX_SHA512 - // sha512 state that absorbed pub_seed - uint8_t state_seeded_512[72]; -# endif -#endif - -#ifdef SPX_HARAKA - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -#endif -} spx_ctx; - -#endif diff --git a/sphincsplus/ref/fips202.c b/sphincsplus/ref/fips202.c deleted file mode 100644 index 8262d91..0000000 --- a/sphincsplus/ref/fips202.c +++ /dev/null @@ -1,598 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/keccakc512/simple/ from http://bench.cr.yp.to/supercop.html - * by Ronny Van Keer - * and the public domain "TweetFips202" implementation - * from https://twitter.com/tweetfips202 - * by Gilles Van Assche, Daniel J. Bernstein, and Peter Schwabe */ - -#include -#include - -#include "fips202.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64 - (offset)))) - -/************************************************* - * Name: load64 - * - * Description: Load 8 bytes into uint64_t in little-endian order - * - * Arguments: - const uint8_t *x: pointer to input byte array - * - * Returns the loaded 64-bit unsigned integer - **************************************************/ -static uint64_t load64(const uint8_t *x) { - uint64_t r = 0; - for (size_t i = 0; i < 8; ++i) { - r |= (uint64_t)x[i] << 8 * i; - } - - return r; -} - -/************************************************* - * Name: store64 - * - * Description: Store a 64-bit integer to a byte array in little-endian order - * - * Arguments: - uint8_t *x: pointer to the output byte array - * - uint64_t u: input 64-bit unsigned integer - **************************************************/ -static void store64(uint8_t *x, uint64_t u) { - for (size_t i = 0; i < 8; ++i) { - x[i] = (uint8_t) (u >> 8 * i); - } -} - -/* Keccak round constants */ -static const uint64_t KeccakF_RoundConstants[NROUNDS] = { - 0x0000000000000001ULL, 0x0000000000008082ULL, - 0x800000000000808aULL, 0x8000000080008000ULL, - 0x000000000000808bULL, 0x0000000080000001ULL, - 0x8000000080008081ULL, 0x8000000000008009ULL, - 0x000000000000008aULL, 0x0000000000000088ULL, - 0x0000000080008009ULL, 0x000000008000000aULL, - 0x000000008000808bULL, 0x800000000000008bULL, - 0x8000000000008089ULL, 0x8000000000008003ULL, - 0x8000000000008002ULL, 0x8000000000000080ULL, - 0x000000000000800aULL, 0x800000008000000aULL, - 0x8000000080008081ULL, 0x8000000000008080ULL, - 0x0000000080000001ULL, 0x8000000080008008ULL -}; - -/************************************************* - * Name: KeccakF1600_StatePermute - * - * Description: The Keccak F1600 Permutation - * - * Arguments: - uint64_t *state: pointer to input/output Keccak state - **************************************************/ -static void KeccakF1600_StatePermute(uint64_t *state) { - int round; - - uint64_t Aba, Abe, Abi, Abo, Abu; - uint64_t Aga, Age, Agi, Ago, Agu; - uint64_t Aka, Ake, Aki, Ako, Aku; - uint64_t Ama, Ame, Ami, Amo, Amu; - uint64_t Asa, Ase, Asi, Aso, Asu; - uint64_t BCa, BCe, BCi, BCo, BCu; - uint64_t Da, De, Di, Do, Du; - uint64_t Eba, Ebe, Ebi, Ebo, Ebu; - uint64_t Ega, Ege, Egi, Ego, Egu; - uint64_t Eka, Eke, Eki, Eko, Eku; - uint64_t Ema, Eme, Emi, Emo, Emu; - uint64_t Esa, Ese, Esi, Eso, Esu; - - // copyFromState(A, state) - Aba = state[0]; - Abe = state[1]; - Abi = state[2]; - Abo = state[3]; - Abu = state[4]; - Aga = state[5]; - Age = state[6]; - Agi = state[7]; - Ago = state[8]; - Agu = state[9]; - Aka = state[10]; - Ake = state[11]; - Aki = state[12]; - Ako = state[13]; - Aku = state[14]; - Ama = state[15]; - Ame = state[16]; - Ami = state[17]; - Amo = state[18]; - Amu = state[19]; - Asa = state[20]; - Ase = state[21]; - Asi = state[22]; - Aso = state[23]; - Asu = state[24]; - - for (round = 0; round < NROUNDS; round += 2) { - // prepareTheta - BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa; - BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase; - BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; - BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; - BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; - - // thetaRhoPiChiIotaPrepareTheta(round , A, E) - Da = BCu ^ ROL(BCe, 1); - De = BCa ^ ROL(BCi, 1); - Di = BCe ^ ROL(BCo, 1); - Do = BCi ^ ROL(BCu, 1); - Du = BCo ^ ROL(BCa, 1); - - Aba ^= Da; - BCa = Aba; - Age ^= De; - BCe = ROL(Age, 44); - Aki ^= Di; - BCi = ROL(Aki, 43); - Amo ^= Do; - BCo = ROL(Amo, 21); - Asu ^= Du; - BCu = ROL(Asu, 14); - Eba = BCa ^ ((~BCe) & BCi); - Eba ^= KeccakF_RoundConstants[round]; - Ebe = BCe ^ ((~BCi) & BCo); - Ebi = BCi ^ ((~BCo) & BCu); - Ebo = BCo ^ ((~BCu) & BCa); - Ebu = BCu ^ ((~BCa) & BCe); - - Abo ^= Do; - BCa = ROL(Abo, 28); - Agu ^= Du; - BCe = ROL(Agu, 20); - Aka ^= Da; - BCi = ROL(Aka, 3); - Ame ^= De; - BCo = ROL(Ame, 45); - Asi ^= Di; - BCu = ROL(Asi, 61); - Ega = BCa ^ ((~BCe) & BCi); - Ege = BCe ^ ((~BCi) & BCo); - Egi = BCi ^ ((~BCo) & BCu); - Ego = BCo ^ ((~BCu) & BCa); - Egu = BCu ^ ((~BCa) & BCe); - - Abe ^= De; - BCa = ROL(Abe, 1); - Agi ^= Di; - BCe = ROL(Agi, 6); - Ako ^= Do; - BCi = ROL(Ako, 25); - Amu ^= Du; - BCo = ROL(Amu, 8); - Asa ^= Da; - BCu = ROL(Asa, 18); - Eka = BCa ^ ((~BCe) & BCi); - Eke = BCe ^ ((~BCi) & BCo); - Eki = BCi ^ ((~BCo) & BCu); - Eko = BCo ^ ((~BCu) & BCa); - Eku = BCu ^ ((~BCa) & BCe); - - Abu ^= Du; - BCa = ROL(Abu, 27); - Aga ^= Da; - BCe = ROL(Aga, 36); - Ake ^= De; - BCi = ROL(Ake, 10); - Ami ^= Di; - BCo = ROL(Ami, 15); - Aso ^= Do; - BCu = ROL(Aso, 56); - Ema = BCa ^ ((~BCe) & BCi); - Eme = BCe ^ ((~BCi) & BCo); - Emi = BCi ^ ((~BCo) & BCu); - Emo = BCo ^ ((~BCu) & BCa); - Emu = BCu ^ ((~BCa) & BCe); - - Abi ^= Di; - BCa = ROL(Abi, 62); - Ago ^= Do; - BCe = ROL(Ago, 55); - Aku ^= Du; - BCi = ROL(Aku, 39); - Ama ^= Da; - BCo = ROL(Ama, 41); - Ase ^= De; - BCu = ROL(Ase, 2); - Esa = BCa ^ ((~BCe) & BCi); - Ese = BCe ^ ((~BCi) & BCo); - Esi = BCi ^ ((~BCo) & BCu); - Eso = BCo ^ ((~BCu) & BCa); - Esu = BCu ^ ((~BCa) & BCe); - - // prepareTheta - BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa; - BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; - BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; - BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; - BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; - - // thetaRhoPiChiIotaPrepareTheta(round+1, E, A) - Da = BCu ^ ROL(BCe, 1); - De = BCa ^ ROL(BCi, 1); - Di = BCe ^ ROL(BCo, 1); - Do = BCi ^ ROL(BCu, 1); - Du = BCo ^ ROL(BCa, 1); - - Eba ^= Da; - BCa = Eba; - Ege ^= De; - BCe = ROL(Ege, 44); - Eki ^= Di; - BCi = ROL(Eki, 43); - Emo ^= Do; - BCo = ROL(Emo, 21); - Esu ^= Du; - BCu = ROL(Esu, 14); - Aba = BCa ^ ((~BCe) & BCi); - Aba ^= KeccakF_RoundConstants[round + 1]; - Abe = BCe ^ ((~BCi) & BCo); - Abi = BCi ^ ((~BCo) & BCu); - Abo = BCo ^ ((~BCu) & BCa); - Abu = BCu ^ ((~BCa) & BCe); - - Ebo ^= Do; - BCa = ROL(Ebo, 28); - Egu ^= Du; - BCe = ROL(Egu, 20); - Eka ^= Da; - BCi = ROL(Eka, 3); - Eme ^= De; - BCo = ROL(Eme, 45); - Esi ^= Di; - BCu = ROL(Esi, 61); - Aga = BCa ^ ((~BCe) & BCi); - Age = BCe ^ ((~BCi) & BCo); - Agi = BCi ^ ((~BCo) & BCu); - Ago = BCo ^ ((~BCu) & BCa); - Agu = BCu ^ ((~BCa) & BCe); - - Ebe ^= De; - BCa = ROL(Ebe, 1); - Egi ^= Di; - BCe = ROL(Egi, 6); - Eko ^= Do; - BCi = ROL(Eko, 25); - Emu ^= Du; - BCo = ROL(Emu, 8); - Esa ^= Da; - BCu = ROL(Esa, 18); - Aka = BCa ^ ((~BCe) & BCi); - Ake = BCe ^ ((~BCi) & BCo); - Aki = BCi ^ ((~BCo) & BCu); - Ako = BCo ^ ((~BCu) & BCa); - Aku = BCu ^ ((~BCa) & BCe); - - Ebu ^= Du; - BCa = ROL(Ebu, 27); - Ega ^= Da; - BCe = ROL(Ega, 36); - Eke ^= De; - BCi = ROL(Eke, 10); - Emi ^= Di; - BCo = ROL(Emi, 15); - Eso ^= Do; - BCu = ROL(Eso, 56); - Ama = BCa ^ ((~BCe) & BCi); - Ame = BCe ^ ((~BCi) & BCo); - Ami = BCi ^ ((~BCo) & BCu); - Amo = BCo ^ ((~BCu) & BCa); - Amu = BCu ^ ((~BCa) & BCe); - - Ebi ^= Di; - BCa = ROL(Ebi, 62); - Ego ^= Do; - BCe = ROL(Ego, 55); - Eku ^= Du; - BCi = ROL(Eku, 39); - Ema ^= Da; - BCo = ROL(Ema, 41); - Ese ^= De; - BCu = ROL(Ese, 2); - Asa = BCa ^ ((~BCe) & BCi); - Ase = BCe ^ ((~BCi) & BCo); - Asi = BCi ^ ((~BCo) & BCu); - Aso = BCo ^ ((~BCu) & BCa); - Asu = BCu ^ ((~BCa) & BCe); - } - - // copyToState(state, A) - state[0] = Aba; - state[1] = Abe; - state[2] = Abi; - state[3] = Abo; - state[4] = Abu; - state[5] = Aga; - state[6] = Age; - state[7] = Agi; - state[8] = Ago; - state[9] = Agu; - state[10] = Aka; - state[11] = Ake; - state[12] = Aki; - state[13] = Ako; - state[14] = Aku; - state[15] = Ama; - state[16] = Ame; - state[17] = Ami; - state[18] = Amo; - state[19] = Amu; - state[20] = Asa; - state[21] = Ase; - state[22] = Asi; - state[23] = Aso; - state[24] = Asu; -} - -/************************************************* - * Name: keccak_absorb - * - * Description: Absorb step of Keccak; - * non-incremental, starts by zeroeing the state. - * - * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state - * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) - * - const uint8_t *m: pointer to input to be absorbed into s - * - size_t mlen: length of input in bytes - * - uint8_t p: domain-separation byte for different - * Keccak-derived functions - **************************************************/ -static void keccak_absorb(uint64_t *s, uint32_t r, const uint8_t *m, - size_t mlen, uint8_t p) { - size_t i; - uint8_t t[200]; - - /* Zero state */ - for (i = 0; i < 25; ++i) { - s[i] = 0; - } - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - s[i] ^= load64(m + 8 * i); - } - - KeccakF1600_StatePermute(s); - mlen -= r; - m += r; - } - - for (i = 0; i < r; ++i) { - t[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t[i] = m[i]; - } - t[i] = p; - t[r - 1] |= 128; - for (i = 0; i < r / 8; ++i) { - s[i] ^= load64(t + 8 * i); - } -} - -/************************************************* - * Name: keccak_squeezeblocks - * - * Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each. - * Modifies the state. Can be called multiple times to keep - * squeezing, i.e., is incremental. - * - * Arguments: - uint8_t *h: pointer to output blocks - * - size_t nblocks: number of blocks to be - * squeezed (written to h) - * - uint64_t *s: pointer to input/output Keccak state - * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) - **************************************************/ -static void keccak_squeezeblocks(uint8_t *h, size_t nblocks, - uint64_t *s, uint32_t r) { - while (nblocks > 0) { - KeccakF1600_StatePermute(s); - for (size_t i = 0; i < (r >> 3); i++) { - store64(h + 8 * i, s[i]); - } - h += r; - nblocks--; - } -} - -/************************************************* - * Name: keccak_inc_init - * - * Description: Initializes the incremental Keccak state to zero. - * - * Arguments: - uint64_t *s_inc: pointer to input/output incremental state - * First 25 values represent Keccak state. - * 26th value represents either the number of absorbed bytes - * that have not been permuted, or not-yet-squeezed bytes. - **************************************************/ -static void keccak_inc_init(uint64_t *s_inc) { - size_t i; - - for (i = 0; i < 25; ++i) { - s_inc[i] = 0; - } - s_inc[25] = 0; -} - -/************************************************* - * Name: keccak_inc_absorb - * - * Description: Incremental keccak absorb - * Preceded by keccak_inc_init, succeeded by keccak_inc_finalize - * - * Arguments: - uint64_t *s_inc: pointer to input/output incremental state - * First 25 values represent Keccak state. - * 26th value represents either the number of absorbed bytes - * that have not been permuted, or not-yet-squeezed bytes. - * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) - * - const uint8_t *m: pointer to input to be absorbed into s - * - size_t mlen: length of input in bytes - **************************************************/ -static void keccak_inc_absorb(uint64_t *s_inc, uint32_t r, const uint8_t *m, - size_t mlen) { - size_t i; - - /* Recall that s_inc[25] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[25] >= r) { - for (i = 0; i < r - s_inc[25]; i++) { - /* Take the i'th byte from message - xor with the s_inc[25] + i'th byte of the state; little-endian */ - s_inc[(s_inc[25] + i) >> 3] ^= (uint64_t)m[i] << (8 * ((s_inc[25] + i) & 0x07)); - } - mlen -= (size_t)(r - s_inc[25]); - m += r - s_inc[25]; - s_inc[25] = 0; - - KeccakF1600_StatePermute(s_inc); - } - - for (i = 0; i < mlen; i++) { - s_inc[(s_inc[25] + i) >> 3] ^= (uint64_t)m[i] << (8 * ((s_inc[25] + i) & 0x07)); - } - s_inc[25] += mlen; -} - -/************************************************* - * Name: keccak_inc_finalize - * - * Description: Finalizes Keccak absorb phase, prepares for squeezing - * - * Arguments: - uint64_t *s_inc: pointer to input/output incremental state - * First 25 values represent Keccak state. - * 26th value represents either the number of absorbed bytes - * that have not been permuted, or not-yet-squeezed bytes. - * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) - * - uint8_t p: domain-separation byte for different - * Keccak-derived functions - **************************************************/ -static void keccak_inc_finalize(uint64_t *s_inc, uint32_t r, uint8_t p) { - /* After keccak_inc_absorb, we are guaranteed that s_inc[25] < r, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[25] >> 3] ^= (uint64_t)p << (8 * (s_inc[25] & 0x07)); - s_inc[(r - 1) >> 3] ^= (uint64_t)128 << (8 * ((r - 1) & 0x07)); - s_inc[25] = 0; -} - -/************************************************* - * Name: keccak_inc_squeeze - * - * Description: Incremental Keccak squeeze; can be called on byte-level - * - * Arguments: - uint8_t *h: pointer to output bytes - * - size_t outlen: number of bytes to be squeezed - * - uint64_t *s_inc: pointer to input/output incremental state - * First 25 values represent Keccak state. - * 26th value represents either the number of absorbed bytes - * that have not been permuted, or not-yet-squeezed bytes. - * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) - **************************************************/ -static void keccak_inc_squeeze(uint8_t *h, size_t outlen, - uint64_t *s_inc, uint32_t r) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[25]; i++) { - /* There are s_inc[25] bytes left, so r - s_inc[25] is the first - available byte. We consume from there, i.e., up to r. */ - h[i] = (uint8_t)(s_inc[(r - s_inc[25] + i) >> 3] >> (8 * ((r - s_inc[25] + i) & 0x07))); - } - h += i; - outlen -= i; - s_inc[25] -= i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - KeccakF1600_StatePermute(s_inc); - - for (i = 0; i < outlen && i < r; i++) { - h[i] = (uint8_t)(s_inc[i >> 3] >> (8 * (i & 0x07))); - } - h += i; - outlen -= i; - s_inc[25] = r - i; - } -} - -void shake256_inc_init(uint64_t *s_inc) { - keccak_inc_init(s_inc); -} - -void shake256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen) { - keccak_inc_absorb(s_inc, SHAKE256_RATE, input, inlen); -} - -void shake256_inc_finalize(uint64_t *s_inc) { - keccak_inc_finalize(s_inc, SHAKE256_RATE, 0x1F); -} - -void shake256_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc) { - keccak_inc_squeeze(output, outlen, s_inc, SHAKE256_RATE); -} - -/************************************************* - * Name: shake256_absorb - * - * Description: Absorb step of the SHAKE256 XOF. - * non-incremental, starts by zeroeing the state. - * - * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state - * - const uint8_t *input: pointer to input to be absorbed - * into s - * - size_t inlen: length of input in bytes - **************************************************/ -void shake256_absorb(uint64_t *s, const uint8_t *input, size_t inlen) { - keccak_absorb(s, SHAKE256_RATE, input, inlen, 0x1F); -} - -/************************************************* - * Name: shake256_squeezeblocks - * - * Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of - * SHAKE256_RATE bytes each. Modifies the state. Can be called - * multiple times to keep squeezing, i.e., is incremental. - * - * Arguments: - uint8_t *output: pointer to output blocks - * - size_t nblocks: number of blocks to be squeezed - * (written to output) - * - uint64_t *s: pointer to input/output Keccak state - **************************************************/ -void shake256_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s) { - keccak_squeezeblocks(output, nblocks, s, SHAKE256_RATE); -} - -/************************************************* - * Name: shake256 - * - * Description: SHAKE256 XOF with non-incremental API - * - * Arguments: - uint8_t *output: pointer to output - * - size_t outlen: requested output length in bytes - * - const uint8_t *input: pointer to input - * - size_t inlen: length of input in bytes - **************************************************/ -void shake256(uint8_t *output, size_t outlen, - const uint8_t *input, size_t inlen) { - size_t nblocks = outlen / SHAKE256_RATE; - uint8_t t[SHAKE256_RATE]; - uint64_t s[25]; - - shake256_absorb(s, input, inlen); - shake256_squeezeblocks(output, nblocks, s); - - output += nblocks * SHAKE256_RATE; - outlen -= nblocks * SHAKE256_RATE; - - if (outlen) { - shake256_squeezeblocks(t, 1, s); - for (size_t i = 0; i < outlen; ++i) { - output[i] = t[i]; - } - } -} diff --git a/sphincsplus/ref/fips202.h b/sphincsplus/ref/fips202.h deleted file mode 100644 index e11cb7f..0000000 --- a/sphincsplus/ref/fips202.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef SPX_FIPS202_H -#define SPX_FIPS202_H - -#include -#include - -#define SHAKE128_RATE 168 -#define SHAKE256_RATE 136 -#define SHA3_256_RATE 136 -#define SHA3_512_RATE 72 - -void shake128_absorb(uint64_t *s, const uint8_t *input, size_t inlen); - -void shake128_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s); - -void shake128_inc_init(uint64_t *s_inc); -void shake128_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); -void shake128_inc_finalize(uint64_t *s_inc); -void shake128_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc); - -void shake256_absorb(uint64_t *s, const uint8_t *input, size_t inlen); -void shake256_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s); - -void shake256_inc_init(uint64_t *s_inc); -void shake256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); -void shake256_inc_finalize(uint64_t *s_inc); -void shake256_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc); - -void shake128(uint8_t *output, size_t outlen, - const uint8_t *input, size_t inlen); - -void shake256(uint8_t *output, size_t outlen, - const uint8_t *input, size_t inlen); - -void sha3_256_inc_init(uint64_t *s_inc); -void sha3_256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); -void sha3_256_inc_finalize(uint8_t *output, uint64_t *s_inc); - -void sha3_256(uint8_t *output, const uint8_t *input, size_t inlen); - -void sha3_512_inc_init(uint64_t *s_inc); -void sha3_512_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); -void sha3_512_inc_finalize(uint8_t *output, uint64_t *s_inc); - -void sha3_512(uint8_t *output, const uint8_t *input, size_t inlen); - -#endif diff --git a/sphincsplus/ref/fors.c b/sphincsplus/ref/fors.c deleted file mode 100644 index e6aa4b4..0000000 --- a/sphincsplus/ref/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "fors.h" -#include "utils.h" -#include "utilsx1.h" -#include "hash.h" -#include "thash.h" -#include "address.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) -{ - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) -{ - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) -{ - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) -{ - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= ((m[offset >> 3] >> (offset & 0x7)) & 1u) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) -{ - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i*SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx* ctx, - const uint32_t fors_addr[8]) -{ - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i*SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/sphincsplus/ref/fors.h b/sphincsplus/ref/fors.h deleted file mode 100644 index 8d98017..0000000 --- a/sphincsplus/ref/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "params.h" -#include "context.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx* ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx* ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/sphincsplus/ref/haraka.c b/sphincsplus/ref/haraka.c deleted file mode 100644 index b9046f2..0000000 --- a/sphincsplus/ref/haraka.c +++ /dev/null @@ -1,965 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin , licensed as follows: - * - * Copyright (c) 2016 Thomas Pornin - * - * 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. - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) -{ - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) -{ - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) -{ - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) -{ - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) -{ - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) -{ -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)cl) | ((b & (uint32_t)cl) << (s)); \ - (y) = ((a & (uint32_t)ch) >> (s)) | (b & (uint32_t)ch); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) -{ - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) -{ - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) -{ - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) -{ - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) -{ -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) -{ - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) -{ - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) -{ - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) -{ - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) -{ - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) -{ - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) -{ - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) -{ - int i; - for (i = 0; i < 4; i++) { - out[2*i] = br_dec32le(in + 4*i); - out[2*i + 1] = br_dec32le(in + 4*i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) -{ - unsigned char buf[40*16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40*16); - - /* Constants for pk.seed */ - haraka_S(buf, 40*16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32*i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64*i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) -{ - unsigned long long i; - SPX_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - mlen -= r; - m += r; - } - - for (i = 0; i < r; ++i) { - t[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t[i] = m[i]; - } - t[i] = p; - t[r - 1] |= 128; - for (i = 0; i < r; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) -{ - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) -{ - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) -{ - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) -{ - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) -{ - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) -{ - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) -{ - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2*i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) -{ - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) -{ - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2*i] = br_dec32le(in + 4*i); - q[2*i + 1] = br_dec32le(in + 4*i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2*i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4*i, q[2*i]); - br_enc32le(out + 4*i + 16, q[2*i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/sphincsplus/ref/haraka.h b/sphincsplus/ref/haraka.h deleted file mode 100644 index 7cd311c..0000000 --- a/sphincsplus/ref/haraka.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/sphincsplus/ref/haraka_offsets.h b/sphincsplus/ref/haraka_offsets.h deleted file mode 100644 index 6afa5f8..0000000 --- a/sphincsplus/ref/haraka_offsets.h +++ /dev/null @@ -1,20 +0,0 @@ -#if !defined( HARAKA_OFFSETS_H_ ) -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR 20 /* The start of the 4 byte field used to specify the key pair address */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/sphincsplus/ref/hash.h b/sphincsplus/ref/hash.h deleted file mode 100644 index b141f09..0000000 --- a/sphincsplus/ref/hash.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include "context.h" -#include "params.h" - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, unsigned long long mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, unsigned long long mlen, - const spx_ctx *ctx); - -#endif diff --git a/sphincsplus/ref/hash_haraka.c b/sphincsplus/ref/hash_haraka.c deleted file mode 100644 index 0c73525..0000000 --- a/sphincsplus/ref/hash_haraka.c +++ /dev/null @@ -1,96 +0,0 @@ -#include -#include - -#include "address.h" -#include "utils.h" -#include "params.h" - -#include "haraka.h" -#include "hash.h" - -void initialize_hash_function(spx_ctx* ctx) -{ - tweak_constants(ctx); -} - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) -{ - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char* sk_prf, - const unsigned char *optrand, - const unsigned char *m, unsigned long long mlen, - const spx_ctx *ctx) -{ - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, unsigned long long mlen, - const spx_ctx *ctx) -{ -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - -#if SPX_TREE_BITS > 64 - #error For given height and depth, 64 bits cannot represent all subtrees -#endif - - if (SPX_D == 1) { - *tree = 0; - } else { - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - } - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/sphincsplus/ref/hash_sha2.c b/sphincsplus/ref/hash_sha2.c deleted file mode 100644 index 67098e6..0000000 --- a/sphincsplus/ref/hash_sha2.c +++ /dev/null @@ -1,197 +0,0 @@ -#include -#include - -#include "address.h" -#include "utils.h" -#include "params.h" -#include "hash.h" -#include "sha2.h" - -#if SPX_N >= 24 -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES -#define shaX_inc_init sha512_inc_init -#define shaX_inc_blocks sha512_inc_blocks -#define shaX_inc_finalize sha512_inc_finalize -#define shaX sha512 -#define mgf1_X mgf1_512 -#else -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES -#define shaX_inc_init sha256_inc_init -#define shaX_inc_blocks sha256_inc_blocks -#define shaX_inc_finalize sha256_inc_finalize -#define shaX sha256 -#define mgf1_X mgf1_256 -#endif - - -/* For SHA, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) -{ - seed_state(ctx); -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) -{ - uint8_t sha2_state[40]; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, ctx->state_seeded, 40 * sizeof(uint8_t)); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, unsigned long long mlen, - const spx_ctx *ctx) -{ - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - uint8_t state[8 + SPX_SHAX_OUTPUT_BYTES]; - int i; - -#if SPX_N > SPX_SHAX_BLOCK_BYTES - #error "Currently only supports SPX_N of at most SPX_SHAX_BLOCK_BYTES" -#endif - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(state); - shaX_inc_blocks(state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, unsigned long long mlen, - const spx_ctx *ctx) -{ - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2*SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#if (SPX_SHAX_BLOCK_BYTES & (SPX_SHAX_BLOCK_BYTES-1)) != 0 - #error "Assumes that SPX_SHAX_BLOCK_BYTES is a power of 2" -#endif -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t state[8 + SPX_SHAX_OUTPUT_BYTES]; - - shaX_inc_init(state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2*SPX_N, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2*SPX_N, state, m, mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2*SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - -#if SPX_TREE_BITS > 64 - #error For given height and depth, 64 bits cannot represent all subtrees -#endif - - if (SPX_D == 1) { - *tree = 0; - } else { - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - } - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/sphincsplus/ref/hash_shake.c b/sphincsplus/ref/hash_shake.c deleted file mode 100644 index f0372bf..0000000 --- a/sphincsplus/ref/hash_shake.c +++ /dev/null @@ -1,97 +0,0 @@ -#include -#include - -#include "address.h" -#include "utils.h" -#include "params.h" -#include "hash.h" -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx* ctx) -{ - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) -{ - unsigned char buf[2*SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2*SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, unsigned long long mlen, - const spx_ctx *ctx) -{ - (void)ctx; - uint64_t s_inc[26]; - - shake256_inc_init(s_inc); - shake256_inc_absorb(s_inc, sk_prf, SPX_N); - shake256_inc_absorb(s_inc, optrand, SPX_N); - shake256_inc_absorb(s_inc, m, mlen); - shake256_inc_finalize(s_inc); - shake256_inc_squeeze(R, SPX_N, s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, unsigned long long mlen, - const spx_ctx *ctx) -{ - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint64_t s_inc[26]; - - shake256_inc_init(s_inc); - shake256_inc_absorb(s_inc, R, SPX_N); - shake256_inc_absorb(s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(s_inc, m, mlen); - shake256_inc_finalize(s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - -#if SPX_TREE_BITS > 64 - #error For given height and depth, 64 bits cannot represent all subtrees -#endif - - if (SPX_D == 1) { - *tree = 0; - } else { - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - } - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/sphincsplus/ref/merkle.c b/sphincsplus/ref/merkle.c deleted file mode 100644 index 414f468..0000000 --- a/sphincsplus/ref/merkle.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" -#include "merkle.h" -#include "address.h" -#include "params.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) -{ - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) -{ - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/sphincsplus/ref/merkle.h b/sphincsplus/ref/merkle.h deleted file mode 100644 index 9ac2759..0000000 --- a/sphincsplus/ref/merkle.h +++ /dev/null @@ -1,18 +0,0 @@ -#if !defined( MERKLE_H_ ) -#define MERKLE_H_ - -#include - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx* ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx* ctx); - -#endif /* MERKLE_H_ */ diff --git a/sphincsplus/ref/params.h b/sphincsplus/ref/params.h deleted file mode 100644 index 1d7f9c9..0000000 --- a/sphincsplus/ref/params.h +++ /dev/null @@ -1,5 +0,0 @@ -#define str(s) #s -#define xstr(s) str(s) - -#include xstr(params/params-PARAMS.h) - diff --git a/sphincsplus/ref/params/params-sphincs-haraka-128f.h b/sphincsplus/ref/params/params-sphincs-haraka-128f.h deleted file mode 100644 index a9bb1cf..0000000 --- a/sphincsplus/ref/params/params-sphincs-haraka-128f.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../haraka_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-haraka-128s.h b/sphincsplus/ref/params/params-sphincs-haraka-128s.h deleted file mode 100644 index 73372ee..0000000 --- a/sphincsplus/ref/params/params-sphincs-haraka-128s.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../haraka_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-haraka-192f.h b/sphincsplus/ref/params/params-sphincs-haraka-192f.h deleted file mode 100644 index 9eb356a..0000000 --- a/sphincsplus/ref/params/params-sphincs-haraka-192f.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../haraka_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-haraka-192s.h b/sphincsplus/ref/params/params-sphincs-haraka-192s.h deleted file mode 100644 index 00b6b70..0000000 --- a/sphincsplus/ref/params/params-sphincs-haraka-192s.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../haraka_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-haraka-256f.h b/sphincsplus/ref/params/params-sphincs-haraka-256f.h deleted file mode 100644 index 7491b66..0000000 --- a/sphincsplus/ref/params/params-sphincs-haraka-256f.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../haraka_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-haraka-256s.h b/sphincsplus/ref/params/params-sphincs-haraka-256s.h deleted file mode 100644 index 6ef3a5c..0000000 --- a/sphincsplus/ref/params/params-sphincs-haraka-256s.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../haraka_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-sha2-128f.h b/sphincsplus/ref/params/params-sphincs-sha2-128f.h deleted file mode 100644 index 3f7a60f..0000000 --- a/sphincsplus/ref/params/params-sphincs-sha2-128f.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../sha2_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-sha2-128s.h b/sphincsplus/ref/params/params-sphincs-sha2-128s.h deleted file mode 100644 index 8ef8608..0000000 --- a/sphincsplus/ref/params/params-sphincs-sha2-128s.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../sha2_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-sha2-192f.h b/sphincsplus/ref/params/params-sphincs-sha2-192f.h deleted file mode 100644 index d4d98a2..0000000 --- a/sphincsplus/ref/params/params-sphincs-sha2-192f.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../sha2_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-sha2-192s.h b/sphincsplus/ref/params/params-sphincs-sha2-192s.h deleted file mode 100644 index 0070e59..0000000 --- a/sphincsplus/ref/params/params-sphincs-sha2-192s.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../sha2_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-sha2-256f.h b/sphincsplus/ref/params/params-sphincs-sha2-256f.h deleted file mode 100644 index 53c5bef..0000000 --- a/sphincsplus/ref/params/params-sphincs-sha2-256f.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../sha2_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-sha2-256s.h b/sphincsplus/ref/params/params-sphincs-sha2-256s.h deleted file mode 100644 index 10c3663..0000000 --- a/sphincsplus/ref/params/params-sphincs-sha2-256s.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../sha2_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-shake-128f.h b/sphincsplus/ref/params/params-sphincs-shake-128f.h deleted file mode 100644 index 8f77692..0000000 --- a/sphincsplus/ref/params/params-sphincs-shake-128f.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../shake_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-shake-128s.h b/sphincsplus/ref/params/params-sphincs-shake-128s.h deleted file mode 100644 index a4d1e13..0000000 --- a/sphincsplus/ref/params/params-sphincs-shake-128s.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../shake_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-shake-192f.h b/sphincsplus/ref/params/params-sphincs-shake-192f.h deleted file mode 100644 index b1e73d1..0000000 --- a/sphincsplus/ref/params/params-sphincs-shake-192f.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../shake_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-shake-192s.h b/sphincsplus/ref/params/params-sphincs-shake-192s.h deleted file mode 100644 index 0882e1c..0000000 --- a/sphincsplus/ref/params/params-sphincs-shake-192s.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../shake_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-shake-256f.h b/sphincsplus/ref/params/params-sphincs-shake-256f.h deleted file mode 100644 index e301c28..0000000 --- a/sphincsplus/ref/params/params-sphincs-shake-256f.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../shake_offsets.h" - -#endif diff --git a/sphincsplus/ref/params/params-sphincs-shake-256s.h b/sphincsplus/ref/params/params-sphincs-shake-256s.h deleted file mode 100644 index 0a96894..0000000 --- a/sphincsplus/ref/params/params-sphincs-shake-256s.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) SPX_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#if SPX_WOTS_W == 256 - #define SPX_WOTS_LOGW 8 -#elif SPX_WOTS_W == 16 - #define SPX_WOTS_LOGW 4 -#else - #error SPX_WOTS_W assumed 16 or 256 -#endif - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#if SPX_WOTS_W == 256 - #if SPX_N <= 1 - #define SPX_WOTS_LEN2 1 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 2 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#elif SPX_WOTS_W == 16 - #if SPX_N <= 8 - #define SPX_WOTS_LEN2 2 - #elif SPX_N <= 136 - #define SPX_WOTS_LEN2 3 - #elif SPX_N <= 256 - #define SPX_WOTS_LEN2 4 - #else - #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} - #endif -#endif - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT - #error SPX_D should always divide SPX_FULL_HEIGHT -#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "../shake_offsets.h" - -#endif diff --git a/sphincsplus/ref/randombytes.c b/sphincsplus/ref/randombytes.c deleted file mode 100644 index cfbca17..0000000 --- a/sphincsplus/ref/randombytes.c +++ /dev/null @@ -1,43 +0,0 @@ -/* -This code was taken from the SPHINCS reference implementation and is public domain. -*/ - -#include -#include - -#include "randombytes.h" - -static int fd = -1; - -void randombytes(unsigned char *x, unsigned long long xlen) -{ - unsigned long long i; - - if (fd == -1) { - for (;;) { - fd = open("/dev/urandom", O_RDONLY); - if (fd != -1) { - break; - } - sleep(1); - } - } - - while (xlen > 0) { - if (xlen < 1048576) { - i = xlen; - } - else { - i = 1048576; - } - - i = (unsigned long long)read(fd, x, i); - if (i < 1) { - sleep(1); - continue; - } - - x += i; - xlen -= i; - } -} diff --git a/sphincsplus/ref/randombytes.h b/sphincsplus/ref/randombytes.h deleted file mode 100644 index 671c1b1..0000000 --- a/sphincsplus/ref/randombytes.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef SPX_RANDOMBYTES_H -#define SPX_RANDOMBYTES_H - -extern void randombytes(unsigned char * x,unsigned long long xlen); - -#endif diff --git a/sphincsplus/ref/randombytes_custom.c b/sphincsplus/ref/randombytes_custom.c deleted file mode 100644 index 9c05aa3..0000000 --- a/sphincsplus/ref/randombytes_custom.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include -#include "randombytes.h" - -/* Forward declaration of our custom implementation from utils.c */ -extern void custom_slh_randombytes_impl(uint8_t *out, size_t outlen); - -/* This function is the original randombytes implementation but calls our custom implementation */ -void randombytes(unsigned char *x, unsigned long long xlen) { - custom_slh_randombytes_impl(x, (size_t)xlen); -} diff --git a/sphincsplus/ref/rng.c b/sphincsplus/ref/rng.c deleted file mode 100644 index 36f5b27..0000000 --- a/sphincsplus/ref/rng.c +++ /dev/null @@ -1,218 +0,0 @@ -// -// rng.c -// -// Created by Bassham, Lawrence E (Fed) on 8/29/17. -// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. -// - -#include -#include "rng.h" -#include -#include -#include - -AES256_CTR_DRBG_struct DRBG_ctx; - -void AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer); - -/* - seedexpander_init() - ctx - stores the current state of an instance of the seed expander - seed - a 32 byte random value - diversifier - an 8 byte diversifier - maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier - */ -int -seedexpander_init(AES_XOF_struct *ctx, - unsigned char *seed, - unsigned char *diversifier, - unsigned long maxlen) -{ - if ( maxlen >= 0x100000000 ) - return RNG_BAD_MAXLEN; - - ctx->length_remaining = maxlen; - - memcpy(ctx->key, seed, 32); - - memcpy(ctx->ctr, diversifier, 8); - ctx->ctr[11] = (unsigned char)(maxlen % 256); - maxlen >>= 8; - ctx->ctr[10] = (unsigned char)(maxlen % 256); - maxlen >>= 8; - ctx->ctr[9] = (unsigned char)(maxlen % 256); - maxlen >>= 8; - ctx->ctr[8] = (unsigned char)(maxlen % 256); - memset(ctx->ctr+12, 0x00, 4); - - ctx->buffer_pos = 16; - memset(ctx->buffer, 0x00, 16); - - return RNG_SUCCESS; -} - -/* - seedexpander() - ctx - stores the current state of an instance of the seed expander - x - returns the XOF data - xlen - number of bytes to return - */ -int -seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen) -{ - unsigned long offset; - - if ( x == NULL ) - return RNG_BAD_OUTBUF; - if ( xlen >= ctx->length_remaining ) - return RNG_BAD_REQ_LEN; - - ctx->length_remaining -= xlen; - - offset = 0; - while ( xlen > 0 ) { - if ( xlen <= (16-ctx->buffer_pos) ) { // buffer has what we need - memcpy(x+offset, ctx->buffer+ctx->buffer_pos, xlen); - ctx->buffer_pos += xlen; - - return RNG_SUCCESS; - } - - // take what's in the buffer - memcpy(x+offset, ctx->buffer+ctx->buffer_pos, 16-ctx->buffer_pos); - xlen -= 16-ctx->buffer_pos; - offset += 16-ctx->buffer_pos; - - AES256_ECB(ctx->key, ctx->ctr, ctx->buffer); - ctx->buffer_pos = 0; - - //increment the counter - for (int i=15; i>=12; i--) { - if ( ctx->ctr[i] == 0xff ) - ctx->ctr[i] = 0x00; - else { - ctx->ctr[i]++; - break; - } - } - - } - - return RNG_SUCCESS; -} - - -static void handleErrors(void) -{ - ERR_print_errors_fp(stderr); - abort(); -} - -// Use whatever AES implementation you have. This uses AES from openSSL library -// key - 256-bit AES key -// ctr - a 128-bit plaintext value -// buffer - a 128-bit ciphertext value -void -AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer) -{ - EVP_CIPHER_CTX *ctx; - - int len; - - /* Create and initialise the context */ - if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); - - if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL)) - handleErrors(); - - if(1 != EVP_EncryptUpdate(ctx, buffer, &len, ctr, 16)) - handleErrors(); - - /* Clean up */ - EVP_CIPHER_CTX_free(ctx); -} - -void -randombytes_init(unsigned char *entropy_input, - unsigned char *personalization_string) -{ - unsigned char seed_material[48]; - - memcpy(seed_material, entropy_input, 48); - if (personalization_string) - for (int i=0; i<48; i++) - seed_material[i] ^= personalization_string[i]; - memset(DRBG_ctx.Key, 0x00, 32); - memset(DRBG_ctx.V, 0x00, 16); - AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V); - DRBG_ctx.reseed_counter = 1; -} - -int -randombytes(unsigned char *x, unsigned long long xlen) -{ - unsigned char block[16]; - int i = 0; - - while ( xlen > 0 ) { - //increment V - for (int j=15; j>=0; j--) { - if ( DRBG_ctx.V[j] == 0xff ) - DRBG_ctx.V[j] = 0x00; - else { - DRBG_ctx.V[j]++; - break; - } - } - AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block); - if ( xlen > 15 ) { - memcpy(x+i, block, 16); - i += 16; - xlen -= 16; - } - else { - memcpy(x+i, block, xlen); - xlen = 0; - } - } - AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V); - DRBG_ctx.reseed_counter++; - - return RNG_SUCCESS; -} - -void -AES256_CTR_DRBG_Update(unsigned char *provided_data, - unsigned char *Key, - unsigned char *V) -{ - unsigned char temp[48]; - - for (int i=0; i<3; i++) { - //increment V - for (int j=15; j>=0; j--) { - if ( V[j] == 0xff ) - V[j] = 0x00; - else { - V[j]++; - break; - } - } - - AES256_ECB(Key, V, temp+16*i); - } - if ( provided_data != NULL ) - for (int i=0; i<48; i++) - temp[i] ^= provided_data[i]; - memcpy(Key, temp, 32); - memcpy(V, temp+32, 16); -} - - - - - - - - - diff --git a/sphincsplus/ref/rng.h b/sphincsplus/ref/rng.h deleted file mode 100644 index c4f1c60..0000000 --- a/sphincsplus/ref/rng.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// rng.h -// -// Created by Bassham, Lawrence E (Fed) on 8/29/17. -// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. -// - -#ifndef rng_h -#define rng_h - -#include - -#define RNG_SUCCESS 0 -#define RNG_BAD_MAXLEN -1 -#define RNG_BAD_OUTBUF -2 -#define RNG_BAD_REQ_LEN -3 - -typedef struct { - unsigned char buffer[16]; - unsigned long buffer_pos; - unsigned long length_remaining; - unsigned char key[32]; - unsigned char ctr[16]; -} AES_XOF_struct; - -typedef struct { - unsigned char Key[32]; - unsigned char V[16]; - int reseed_counter; -} AES256_CTR_DRBG_struct; - - -void -AES256_CTR_DRBG_Update(unsigned char *provided_data, - unsigned char *Key, - unsigned char *V); - -int -seedexpander_init(AES_XOF_struct *ctx, - unsigned char *seed, - unsigned char *diversifier, - unsigned long maxlen); - -int -seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen); - -void -randombytes_init(unsigned char *entropy_input, - unsigned char *personalization_string); - -int -randombytes(unsigned char *x, unsigned long long xlen); - -#endif /* rng_h */ diff --git a/sphincsplus/ref/sha2.c b/sphincsplus/ref/sha2.c deleted file mode 100644 index ef73047..0000000 --- a/sphincsplus/ref/sha2.c +++ /dev/null @@ -1,700 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "utils.h" -#include "sha2.h" - -static uint32_t load_bigendian_32(const uint8_t *x) { - return (uint32_t)(x[3]) | (((uint32_t)(x[2])) << 8) | - (((uint32_t)(x[1])) << 16) | (((uint32_t)(x[0])) << 24); -} - -static uint64_t load_bigendian_64(const uint8_t *x) { - return (uint64_t)(x[7]) | (((uint64_t)(x[6])) << 8) | - (((uint64_t)(x[5])) << 16) | (((uint64_t)(x[4])) << 24) | - (((uint64_t)(x[3])) << 32) | (((uint64_t)(x[2])) << 40) | - (((uint64_t)(x[1])) << 48) | (((uint64_t)(x[0])) << 56); -} - -static void store_bigendian_32(uint8_t *x, uint64_t u) { - x[3] = (uint8_t) u; - u >>= 8; - x[2] = (uint8_t) u; - u >>= 8; - x[1] = (uint8_t) u; - u >>= 8; - x[0] = (uint8_t) u; -} - -static void store_bigendian_64(uint8_t *x, uint64_t u) { - x[7] = (uint8_t) u; - u >>= 8; - x[6] = (uint8_t) u; - u >>= 8; - x[5] = (uint8_t) u; - u >>= 8; - x[4] = (uint8_t) u; - u >>= 8; - x[3] = (uint8_t) u; - u >>= 8; - x[2] = (uint8_t) u; - u >>= 8; - x[1] = (uint8_t) u; - u >>= 8; - x[0] = (uint8_t) u; -} - -#define SHR(x, c) ((x) >> (c)) -#define ROTR_32(x, c) (((x) >> (c)) | ((x) << (32 - (c)))) -#define ROTR_64(x,c) (((x) >> (c)) | ((x) << (64 - (c)))) - -#define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) -#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - -#define Sigma0_32(x) (ROTR_32(x, 2) ^ ROTR_32(x,13) ^ ROTR_32(x,22)) -#define Sigma1_32(x) (ROTR_32(x, 6) ^ ROTR_32(x,11) ^ ROTR_32(x,25)) -#define sigma0_32(x) (ROTR_32(x, 7) ^ ROTR_32(x,18) ^ SHR(x, 3)) -#define sigma1_32(x) (ROTR_32(x,17) ^ ROTR_32(x,19) ^ SHR(x,10)) - -#define Sigma0_64(x) (ROTR_64(x,28) ^ ROTR_64(x,34) ^ ROTR_64(x,39)) -#define Sigma1_64(x) (ROTR_64(x,14) ^ ROTR_64(x,18) ^ ROTR_64(x,41)) -#define sigma0_64(x) (ROTR_64(x, 1) ^ ROTR_64(x, 8) ^ SHR(x,7)) -#define sigma1_64(x) (ROTR_64(x,19) ^ ROTR_64(x,61) ^ SHR(x,6)) - -#define M_32(w0, w14, w9, w1) w0 = sigma1_32(w14) + (w9) + sigma0_32(w1) + (w0); -#define M_64(w0, w14, w9, w1) w0 = sigma1_64(w14) + (w9) + sigma0_64(w1) + (w0); - -#define EXPAND_32 \ - M_32(w0, w14, w9, w1) \ - M_32(w1, w15, w10, w2) \ - M_32(w2, w0, w11, w3) \ - M_32(w3, w1, w12, w4) \ - M_32(w4, w2, w13, w5) \ - M_32(w5, w3, w14, w6) \ - M_32(w6, w4, w15, w7) \ - M_32(w7, w5, w0, w8) \ - M_32(w8, w6, w1, w9) \ - M_32(w9, w7, w2, w10) \ - M_32(w10, w8, w3, w11) \ - M_32(w11, w9, w4, w12) \ - M_32(w12, w10, w5, w13) \ - M_32(w13, w11, w6, w14) \ - M_32(w14, w12, w7, w15) \ - M_32(w15, w13, w8, w0) - -#define EXPAND_64 \ - M_64(w0 ,w14,w9 ,w1 ) \ - M_64(w1 ,w15,w10,w2 ) \ - M_64(w2 ,w0 ,w11,w3 ) \ - M_64(w3 ,w1 ,w12,w4 ) \ - M_64(w4 ,w2 ,w13,w5 ) \ - M_64(w5 ,w3 ,w14,w6 ) \ - M_64(w6 ,w4 ,w15,w7 ) \ - M_64(w7 ,w5 ,w0 ,w8 ) \ - M_64(w8 ,w6 ,w1 ,w9 ) \ - M_64(w9 ,w7 ,w2 ,w10) \ - M_64(w10,w8 ,w3 ,w11) \ - M_64(w11,w9 ,w4 ,w12) \ - M_64(w12,w10,w5 ,w13) \ - M_64(w13,w11,w6 ,w14) \ - M_64(w14,w12,w7 ,w15) \ - M_64(w15,w13,w8 ,w0 ) - -#define F_32(w, k) \ - T1 = h + Sigma1_32(e) + Ch(e, f, g) + (k) + (w); \ - T2 = Sigma0_32(a) + Maj(a, b, c); \ - h = g; \ - g = f; \ - f = e; \ - e = d + T1; \ - d = c; \ - c = b; \ - b = a; \ - a = T1 + T2; - -#define F_64(w,k) \ - T1 = h + Sigma1_64(e) + Ch(e,f,g) + k + w; \ - T2 = Sigma0_64(a) + Maj(a,b,c); \ - h = g; \ - g = f; \ - f = e; \ - e = d + T1; \ - d = c; \ - c = b; \ - b = a; \ - a = T1 + T2; - -static size_t crypto_hashblocks_sha256(uint8_t *statebytes, - const uint8_t *in, size_t inlen) { - uint32_t state[8]; - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; - uint32_t e; - uint32_t f; - uint32_t g; - uint32_t h; - uint32_t T1; - uint32_t T2; - - a = load_bigendian_32(statebytes + 0); - state[0] = a; - b = load_bigendian_32(statebytes + 4); - state[1] = b; - c = load_bigendian_32(statebytes + 8); - state[2] = c; - d = load_bigendian_32(statebytes + 12); - state[3] = d; - e = load_bigendian_32(statebytes + 16); - state[4] = e; - f = load_bigendian_32(statebytes + 20); - state[5] = f; - g = load_bigendian_32(statebytes + 24); - state[6] = g; - h = load_bigendian_32(statebytes + 28); - state[7] = h; - - while (inlen >= 64) { - uint32_t w0 = load_bigendian_32(in + 0); - uint32_t w1 = load_bigendian_32(in + 4); - uint32_t w2 = load_bigendian_32(in + 8); - uint32_t w3 = load_bigendian_32(in + 12); - uint32_t w4 = load_bigendian_32(in + 16); - uint32_t w5 = load_bigendian_32(in + 20); - uint32_t w6 = load_bigendian_32(in + 24); - uint32_t w7 = load_bigendian_32(in + 28); - uint32_t w8 = load_bigendian_32(in + 32); - uint32_t w9 = load_bigendian_32(in + 36); - uint32_t w10 = load_bigendian_32(in + 40); - uint32_t w11 = load_bigendian_32(in + 44); - uint32_t w12 = load_bigendian_32(in + 48); - uint32_t w13 = load_bigendian_32(in + 52); - uint32_t w14 = load_bigendian_32(in + 56); - uint32_t w15 = load_bigendian_32(in + 60); - - F_32(w0, 0x428a2f98) - F_32(w1, 0x71374491) - F_32(w2, 0xb5c0fbcf) - F_32(w3, 0xe9b5dba5) - F_32(w4, 0x3956c25b) - F_32(w5, 0x59f111f1) - F_32(w6, 0x923f82a4) - F_32(w7, 0xab1c5ed5) - F_32(w8, 0xd807aa98) - F_32(w9, 0x12835b01) - F_32(w10, 0x243185be) - F_32(w11, 0x550c7dc3) - F_32(w12, 0x72be5d74) - F_32(w13, 0x80deb1fe) - F_32(w14, 0x9bdc06a7) - F_32(w15, 0xc19bf174) - - EXPAND_32 - - F_32(w0, 0xe49b69c1) - F_32(w1, 0xefbe4786) - F_32(w2, 0x0fc19dc6) - F_32(w3, 0x240ca1cc) - F_32(w4, 0x2de92c6f) - F_32(w5, 0x4a7484aa) - F_32(w6, 0x5cb0a9dc) - F_32(w7, 0x76f988da) - F_32(w8, 0x983e5152) - F_32(w9, 0xa831c66d) - F_32(w10, 0xb00327c8) - F_32(w11, 0xbf597fc7) - F_32(w12, 0xc6e00bf3) - F_32(w13, 0xd5a79147) - F_32(w14, 0x06ca6351) - F_32(w15, 0x14292967) - - EXPAND_32 - - F_32(w0, 0x27b70a85) - F_32(w1, 0x2e1b2138) - F_32(w2, 0x4d2c6dfc) - F_32(w3, 0x53380d13) - F_32(w4, 0x650a7354) - F_32(w5, 0x766a0abb) - F_32(w6, 0x81c2c92e) - F_32(w7, 0x92722c85) - F_32(w8, 0xa2bfe8a1) - F_32(w9, 0xa81a664b) - F_32(w10, 0xc24b8b70) - F_32(w11, 0xc76c51a3) - F_32(w12, 0xd192e819) - F_32(w13, 0xd6990624) - F_32(w14, 0xf40e3585) - F_32(w15, 0x106aa070) - - EXPAND_32 - - F_32(w0, 0x19a4c116) - F_32(w1, 0x1e376c08) - F_32(w2, 0x2748774c) - F_32(w3, 0x34b0bcb5) - F_32(w4, 0x391c0cb3) - F_32(w5, 0x4ed8aa4a) - F_32(w6, 0x5b9cca4f) - F_32(w7, 0x682e6ff3) - F_32(w8, 0x748f82ee) - F_32(w9, 0x78a5636f) - F_32(w10, 0x84c87814) - F_32(w11, 0x8cc70208) - F_32(w12, 0x90befffa) - F_32(w13, 0xa4506ceb) - F_32(w14, 0xbef9a3f7) - F_32(w15, 0xc67178f2) - - a += state[0]; - b += state[1]; - c += state[2]; - d += state[3]; - e += state[4]; - f += state[5]; - g += state[6]; - h += state[7]; - - state[0] = a; - state[1] = b; - state[2] = c; - state[3] = d; - state[4] = e; - state[5] = f; - state[6] = g; - state[7] = h; - - in += 64; - inlen -= 64; - } - - store_bigendian_32(statebytes + 0, state[0]); - store_bigendian_32(statebytes + 4, state[1]); - store_bigendian_32(statebytes + 8, state[2]); - store_bigendian_32(statebytes + 12, state[3]); - store_bigendian_32(statebytes + 16, state[4]); - store_bigendian_32(statebytes + 20, state[5]); - store_bigendian_32(statebytes + 24, state[6]); - store_bigendian_32(statebytes + 28, state[7]); - - return inlen; -} - -static int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen) -{ - uint64_t state[8]; - uint64_t a; - uint64_t b; - uint64_t c; - uint64_t d; - uint64_t e; - uint64_t f; - uint64_t g; - uint64_t h; - uint64_t T1; - uint64_t T2; - - a = load_bigendian_64(statebytes + 0); state[0] = a; - b = load_bigendian_64(statebytes + 8); state[1] = b; - c = load_bigendian_64(statebytes + 16); state[2] = c; - d = load_bigendian_64(statebytes + 24); state[3] = d; - e = load_bigendian_64(statebytes + 32); state[4] = e; - f = load_bigendian_64(statebytes + 40); state[5] = f; - g = load_bigendian_64(statebytes + 48); state[6] = g; - h = load_bigendian_64(statebytes + 56); state[7] = h; - - while (inlen >= 128) { - uint64_t w0 = load_bigendian_64(in + 0); - uint64_t w1 = load_bigendian_64(in + 8); - uint64_t w2 = load_bigendian_64(in + 16); - uint64_t w3 = load_bigendian_64(in + 24); - uint64_t w4 = load_bigendian_64(in + 32); - uint64_t w5 = load_bigendian_64(in + 40); - uint64_t w6 = load_bigendian_64(in + 48); - uint64_t w7 = load_bigendian_64(in + 56); - uint64_t w8 = load_bigendian_64(in + 64); - uint64_t w9 = load_bigendian_64(in + 72); - uint64_t w10 = load_bigendian_64(in + 80); - uint64_t w11 = load_bigendian_64(in + 88); - uint64_t w12 = load_bigendian_64(in + 96); - uint64_t w13 = load_bigendian_64(in + 104); - uint64_t w14 = load_bigendian_64(in + 112); - uint64_t w15 = load_bigendian_64(in + 120); - - F_64(w0 ,0x428a2f98d728ae22ULL) - F_64(w1 ,0x7137449123ef65cdULL) - F_64(w2 ,0xb5c0fbcfec4d3b2fULL) - F_64(w3 ,0xe9b5dba58189dbbcULL) - F_64(w4 ,0x3956c25bf348b538ULL) - F_64(w5 ,0x59f111f1b605d019ULL) - F_64(w6 ,0x923f82a4af194f9bULL) - F_64(w7 ,0xab1c5ed5da6d8118ULL) - F_64(w8 ,0xd807aa98a3030242ULL) - F_64(w9 ,0x12835b0145706fbeULL) - F_64(w10,0x243185be4ee4b28cULL) - F_64(w11,0x550c7dc3d5ffb4e2ULL) - F_64(w12,0x72be5d74f27b896fULL) - F_64(w13,0x80deb1fe3b1696b1ULL) - F_64(w14,0x9bdc06a725c71235ULL) - F_64(w15,0xc19bf174cf692694ULL) - - EXPAND_64 - - F_64(w0 ,0xe49b69c19ef14ad2ULL) - F_64(w1 ,0xefbe4786384f25e3ULL) - F_64(w2 ,0x0fc19dc68b8cd5b5ULL) - F_64(w3 ,0x240ca1cc77ac9c65ULL) - F_64(w4 ,0x2de92c6f592b0275ULL) - F_64(w5 ,0x4a7484aa6ea6e483ULL) - F_64(w6 ,0x5cb0a9dcbd41fbd4ULL) - F_64(w7 ,0x76f988da831153b5ULL) - F_64(w8 ,0x983e5152ee66dfabULL) - F_64(w9 ,0xa831c66d2db43210ULL) - F_64(w10,0xb00327c898fb213fULL) - F_64(w11,0xbf597fc7beef0ee4ULL) - F_64(w12,0xc6e00bf33da88fc2ULL) - F_64(w13,0xd5a79147930aa725ULL) - F_64(w14,0x06ca6351e003826fULL) - F_64(w15,0x142929670a0e6e70ULL) - - EXPAND_64 - - F_64(w0 ,0x27b70a8546d22ffcULL) - F_64(w1 ,0x2e1b21385c26c926ULL) - F_64(w2 ,0x4d2c6dfc5ac42aedULL) - F_64(w3 ,0x53380d139d95b3dfULL) - F_64(w4 ,0x650a73548baf63deULL) - F_64(w5 ,0x766a0abb3c77b2a8ULL) - F_64(w6 ,0x81c2c92e47edaee6ULL) - F_64(w7 ,0x92722c851482353bULL) - F_64(w8 ,0xa2bfe8a14cf10364ULL) - F_64(w9 ,0xa81a664bbc423001ULL) - F_64(w10,0xc24b8b70d0f89791ULL) - F_64(w11,0xc76c51a30654be30ULL) - F_64(w12,0xd192e819d6ef5218ULL) - F_64(w13,0xd69906245565a910ULL) - F_64(w14,0xf40e35855771202aULL) - F_64(w15,0x106aa07032bbd1b8ULL) - - EXPAND_64 - - F_64(w0 ,0x19a4c116b8d2d0c8ULL) - F_64(w1 ,0x1e376c085141ab53ULL) - F_64(w2 ,0x2748774cdf8eeb99ULL) - F_64(w3 ,0x34b0bcb5e19b48a8ULL) - F_64(w4 ,0x391c0cb3c5c95a63ULL) - F_64(w5 ,0x4ed8aa4ae3418acbULL) - F_64(w6 ,0x5b9cca4f7763e373ULL) - F_64(w7 ,0x682e6ff3d6b2b8a3ULL) - F_64(w8 ,0x748f82ee5defb2fcULL) - F_64(w9 ,0x78a5636f43172f60ULL) - F_64(w10,0x84c87814a1f0ab72ULL) - F_64(w11,0x8cc702081a6439ecULL) - F_64(w12,0x90befffa23631e28ULL) - F_64(w13,0xa4506cebde82bde9ULL) - F_64(w14,0xbef9a3f7b2c67915ULL) - F_64(w15,0xc67178f2e372532bULL) - - EXPAND_64 - - F_64(w0 ,0xca273eceea26619cULL) - F_64(w1 ,0xd186b8c721c0c207ULL) - F_64(w2 ,0xeada7dd6cde0eb1eULL) - F_64(w3 ,0xf57d4f7fee6ed178ULL) - F_64(w4 ,0x06f067aa72176fbaULL) - F_64(w5 ,0x0a637dc5a2c898a6ULL) - F_64(w6 ,0x113f9804bef90daeULL) - F_64(w7 ,0x1b710b35131c471bULL) - F_64(w8 ,0x28db77f523047d84ULL) - F_64(w9 ,0x32caab7b40c72493ULL) - F_64(w10,0x3c9ebe0a15c9bebcULL) - F_64(w11,0x431d67c49c100d4cULL) - F_64(w12,0x4cc5d4becb3e42b6ULL) - F_64(w13,0x597f299cfc657e2aULL) - F_64(w14,0x5fcb6fab3ad6faecULL) - F_64(w15,0x6c44198c4a475817ULL) - - a += state[0]; - b += state[1]; - c += state[2]; - d += state[3]; - e += state[4]; - f += state[5]; - g += state[6]; - h += state[7]; - - state[0] = a; - state[1] = b; - state[2] = c; - state[3] = d; - state[4] = e; - state[5] = f; - state[6] = g; - state[7] = h; - - in += 128; - inlen -= 128; - } - - store_bigendian_64(statebytes + 0,state[0]); - store_bigendian_64(statebytes + 8,state[1]); - store_bigendian_64(statebytes + 16,state[2]); - store_bigendian_64(statebytes + 24,state[3]); - store_bigendian_64(statebytes + 32,state[4]); - store_bigendian_64(statebytes + 40,state[5]); - store_bigendian_64(statebytes + 48,state[6]); - store_bigendian_64(statebytes + 56,state[7]); - - return inlen; -} - - -static const uint8_t iv_256[32] = { - 0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, 0x85, - 0x3c, 0x6e, 0xf3, 0x72, 0xa5, 0x4f, 0xf5, 0x3a, - 0x51, 0x0e, 0x52, 0x7f, 0x9b, 0x05, 0x68, 0x8c, - 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19 -}; - -static const uint8_t iv_512[64] = { - 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xbb, 0x67, 0xae, - 0x85, 0x84, 0xca, 0xa7, 0x3b, 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, - 0xf8, 0x2b, 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1, 0x51, - 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1, 0x9b, 0x05, 0x68, 0x8c, - 0x2b, 0x3e, 0x6c, 0x1f, 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, - 0x6b, 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79 -}; - -void sha256_inc_init(uint8_t *state) { - for (size_t i = 0; i < 32; ++i) { - state[i] = iv_256[i]; - } - for (size_t i = 32; i < 40; ++i) { - state[i] = 0; - } -} - -void sha512_inc_init(uint8_t *state) { - for (size_t i = 0; i < 64; ++i) { - state[i] = iv_512[i]; - } - for (size_t i = 64; i < 72; ++i) { - state[i] = 0; - } -} - -void sha256_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks) { - uint64_t bytes = load_bigendian_64(state + 32); - - crypto_hashblocks_sha256(state, in, 64 * inblocks); - bytes += 64 * inblocks; - - store_bigendian_64(state + 32, bytes); -} - -void sha512_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks) { - uint64_t bytes = load_bigendian_64(state + 64); - - crypto_hashblocks_sha512(state, in, 128 * inblocks); - bytes += 128 * inblocks; - - store_bigendian_64(state + 64, bytes); -} - -void sha256_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen) { - uint8_t padded[128]; - uint64_t bytes = load_bigendian_64(state + 32) + inlen; - - crypto_hashblocks_sha256(state, in, inlen); - in += inlen; - inlen &= 63; - in -= inlen; - - for (size_t i = 0; i < inlen; ++i) { - padded[i] = in[i]; - } - padded[inlen] = 0x80; - - if (inlen < 56) { - for (size_t i = inlen + 1; i < 56; ++i) { - padded[i] = 0; - } - padded[56] = (uint8_t) (bytes >> 53); - padded[57] = (uint8_t) (bytes >> 45); - padded[58] = (uint8_t) (bytes >> 37); - padded[59] = (uint8_t) (bytes >> 29); - padded[60] = (uint8_t) (bytes >> 21); - padded[61] = (uint8_t) (bytes >> 13); - padded[62] = (uint8_t) (bytes >> 5); - padded[63] = (uint8_t) (bytes << 3); - crypto_hashblocks_sha256(state, padded, 64); - } else { - for (size_t i = inlen + 1; i < 120; ++i) { - padded[i] = 0; - } - padded[120] = (uint8_t) (bytes >> 53); - padded[121] = (uint8_t) (bytes >> 45); - padded[122] = (uint8_t) (bytes >> 37); - padded[123] = (uint8_t) (bytes >> 29); - padded[124] = (uint8_t) (bytes >> 21); - padded[125] = (uint8_t) (bytes >> 13); - padded[126] = (uint8_t) (bytes >> 5); - padded[127] = (uint8_t) (bytes << 3); - crypto_hashblocks_sha256(state, padded, 128); - } - - for (size_t i = 0; i < 32; ++i) { - out[i] = state[i]; - } - -} - -void sha512_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen) { - uint8_t padded[256]; - uint64_t bytes = load_bigendian_64(state + 64) + inlen; - - crypto_hashblocks_sha512(state, in, inlen); - in += inlen; - inlen &= 127; - in -= inlen; - - for (size_t i = 0; i < inlen; ++i) { - padded[i] = in[i]; - } - padded[inlen] = 0x80; - - if (inlen < 112) { - for (size_t i = inlen + 1; i < 119; ++i) { - padded[i] = 0; - } - padded[119] = (uint8_t) (bytes >> 61); - padded[120] = (uint8_t) (bytes >> 53); - padded[121] = (uint8_t) (bytes >> 45); - padded[122] = (uint8_t) (bytes >> 37); - padded[123] = (uint8_t) (bytes >> 29); - padded[124] = (uint8_t) (bytes >> 21); - padded[125] = (uint8_t) (bytes >> 13); - padded[126] = (uint8_t) (bytes >> 5); - padded[127] = (uint8_t) (bytes << 3); - crypto_hashblocks_sha512(state, padded, 128); - } else { - for (size_t i = inlen + 1; i < 247; ++i) { - padded[i] = 0; - } - padded[247] = (uint8_t) (bytes >> 61); - padded[248] = (uint8_t) (bytes >> 53); - padded[249] = (uint8_t) (bytes >> 45); - padded[250] = (uint8_t) (bytes >> 37); - padded[251] = (uint8_t) (bytes >> 29); - padded[252] = (uint8_t) (bytes >> 21); - padded[253] = (uint8_t) (bytes >> 13); - padded[254] = (uint8_t) (bytes >> 5); - padded[255] = (uint8_t) (bytes << 3); - crypto_hashblocks_sha512(state, padded, 256); - } - - for (size_t i = 0; i < 64; ++i) { - out[i] = state[i]; - } -} - -void sha256(uint8_t *out, const uint8_t *in, size_t inlen) { - uint8_t state[40]; - - sha256_inc_init(state); - sha256_inc_finalize(out, state, in, inlen); -} - -void sha512(uint8_t *out, const uint8_t *in, size_t inlen) { - uint8_t state[72]; - - sha512_inc_init(state); - sha512_inc_finalize(out, state, in, inlen); -} - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) -{ - SPX_VLA(uint8_t, inbuf, inlen+4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - unsigned long i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i+1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i*SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i*SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) -{ - SPX_VLA(uint8_t, inbuf, inlen+4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - unsigned long i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i+1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i*SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i*SPX_SHA512_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(ctx->state_seeded); - sha256_inc_blocks(ctx->state_seeded, block, 1); -#if SPX_SHA512 - sha512_inc_init(ctx->state_seeded_512); - sha512_inc_blocks(ctx->state_seeded_512, block, 1); -#endif -} diff --git a/sphincsplus/ref/sha2.h b/sphincsplus/ref/sha2.h deleted file mode 100644 index 732ab4b..0000000 --- a/sphincsplus/ref/sha2.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef SPX_SHA2_H -#define SPX_SHA2_H - -#include "params.h" - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal SPX_N */ - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -#if SPX_SHA256_OUTPUT_BYTES < SPX_N - #error Linking against SHA-256 with N larger than 32 bytes is not supported -#endif - -#define SPX_SHA256_ADDR_BYTES 22 - -#include -#include - -void sha256_inc_init(uint8_t *state); -void sha256_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks); -void sha256_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen); -void sha256(uint8_t *out, const uint8_t *in, size_t inlen); - -void sha512_inc_init(uint8_t *state); -void sha512_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks); -void sha512_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen); -void sha512(uint8_t *out, const uint8_t *in, size_t inlen); - -#define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#define seed_state SPX_NAMESPACE(seed_state) -void seed_state(spx_ctx *ctx); - - -#endif diff --git a/sphincsplus/ref/sha2_offsets.h b/sphincsplus/ref/sha2_offsets.h deleted file mode 100644 index 49f7e85..0000000 --- a/sphincsplus/ref/sha2_offsets.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR 10 /* The start of the 4 byte field used to specify the key pair address */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/sphincsplus/ref/shake_offsets.h b/sphincsplus/ref/shake_offsets.h deleted file mode 100644 index 0407bdf..0000000 --- a/sphincsplus/ref/shake_offsets.h +++ /dev/null @@ -1,20 +0,0 @@ -#if !defined( SHAKE_OFFSETS_H_ ) -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR 20 /* The start of the 4 byte field used to specify the key pair address */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/sphincsplus/ref/sign.c b/sphincsplus/ref/sign.c deleted file mode 100644 index a8e0c3c..0000000 --- a/sphincsplus/ref/sign.c +++ /dev/null @@ -1,287 +0,0 @@ -#include -#include -#include - -#include "api.h" -#include "params.h" -#include "wots.h" -#include "fors.h" -#include "hash.h" -#include "thash.h" -#include "address.h" -#include "randombytes.h" -#include "utils.h" -#include "merkle.h" - -/* - * Returns the length of a secret key, in bytes - */ -unsigned long long crypto_sign_secretkeybytes(void) -{ - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -unsigned long long crypto_sign_publickeybytes(void) -{ - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -unsigned long long crypto_sign_bytes(void) -{ - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -unsigned long long crypto_sign_seedbytes(void) -{ - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, - const unsigned char *seed) -{ - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2*SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3*SPX_N, &ctx); - - memcpy(pk + SPX_N, sk + 3*SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) -{ - unsigned char seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) -{ - spx_ctx ctx; - - const unsigned char *sk_prf = sk + SPX_N; - const unsigned char *pk = sk + 2*SPX_N; - - unsigned char optrand[SPX_N]; - unsigned char mhash[SPX_FORS_MSG_BYTES]; - unsigned char root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT)-1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) -{ - spx_ctx ctx; - const unsigned char *pub_root = pk + SPX_N; - unsigned char mhash[SPX_FORS_MSG_BYTES]; - unsigned char wots_pk[SPX_WOTS_BYTES]; - unsigned char root[SPX_N]; - unsigned char leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT)-1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N)) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(unsigned char *sm, unsigned long long *smlen, - const unsigned char *m, unsigned long long mlen, - const unsigned char *sk) -{ - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, (size_t)mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(unsigned char *m, unsigned long long *mlen, - const unsigned char *sm, unsigned long long smlen, - const unsigned char *pk) -{ - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, (size_t)*mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/sphincsplus/ref/test/benchmark.c b/sphincsplus/ref/test/benchmark.c deleted file mode 100644 index b062545..0000000 --- a/sphincsplus/ref/test/benchmark.c +++ /dev/null @@ -1,173 +0,0 @@ -#define _POSIX_C_SOURCE 199309L - -#include -#include -#include - -#include "../thash.h" -#include "../api.h" -#include "../fors.h" -#include "../wotsx1.h" -#include "../params.h" -#include "../randombytes.h" -#include "cycles.h" - -#define SPX_MLEN 32 -#define NTESTS 10 - -static void wots_gen_pkx1(unsigned char *pk, const spx_ctx* ctx, - uint32_t addr[8]); - -static int cmp_llu(const void *a, const void*b) -{ - if(*(unsigned long long *)a < *(unsigned long long *)b) return -1; - if(*(unsigned long long *)a > *(unsigned long long *)b) return 1; - return 0; -} - -static unsigned long long median(unsigned long long *l, size_t llen) -{ - qsort(l,llen,sizeof(unsigned long long),cmp_llu); - - if(llen%2) return l[llen/2]; - else return (l[llen/2-1]+l[llen/2])/2; -} - -static void delta(unsigned long long *l, size_t llen) -{ - unsigned int i; - for(i = 0; i < llen - 1; i++) { - l[i] = l[i+1] - l[i]; - } -} - - -static void printfcomma (unsigned long long n) -{ - if (n < 1000) { - printf("%llu", n); - return; - } - printfcomma(n / 1000); - printf (",%03llu", n % 1000); -} - -static void printfalignedcomma (unsigned long long n, int len) -{ - unsigned long long ncopy = n; - int i = 0; - - while (ncopy > 9) { - len -= 1; - ncopy /= 10; - i += 1; // to account for commas - } - i = i/3 - 1; // to account for commas - for (; i < len; i++) { - printf(" "); - } - printfcomma(n); -} - -static void display_result(double result, unsigned long long *l, size_t llen, unsigned long long mul) -{ - unsigned long long med; - - result /= NTESTS; - delta(l, NTESTS + 1); - med = median(l, llen); - printf("avg. %11.2lf us (%2.2lf sec); median ", result, result / 1e6); - printfalignedcomma(med, 12); - printf(" cycles, %5llux: ", mul); - printfalignedcomma(mul*med, 12); - printf(" cycles\n"); -} - -#define MEASURE_GENERIC(TEXT, MUL, FNCALL, CORR)\ - printf(TEXT);\ - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);\ - for(i = 0; i < NTESTS; i++) {\ - t[i] = cpucycles() / CORR;\ - FNCALL;\ - }\ - t[NTESTS] = cpucycles();\ - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop);\ - result = ((stop.tv_sec - start.tv_sec) * 1e6 + \ - (stop.tv_nsec - start.tv_nsec) / 1e3) / (double)CORR;\ - display_result(result, t, NTESTS, MUL); -#define MEASURT(TEXT, MUL, FNCALL)\ - MEASURE_GENERIC(\ - TEXT, MUL,\ - do {\ - for (int j = 0; j < 1000; j++) {\ - FNCALL;\ - }\ - } while (0);,\ - 1000); -#define MEASURE(TEXT, MUL, FNCALL) MEASURE_GENERIC(TEXT, MUL, FNCALL, 1) - -int main(void) -{ - /* Make stdout buffer more responsive. */ - setbuf(stdout, NULL); - init_cpucycles(); - - spx_ctx ctx; - - unsigned char pk[SPX_PK_BYTES]; - unsigned char sk[SPX_SK_BYTES]; - unsigned char *m = malloc(SPX_MLEN); - unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); - unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); - - unsigned char fors_pk[SPX_FORS_PK_BYTES]; - unsigned char fors_m[SPX_FORS_MSG_BYTES]; - unsigned char fors_sig[SPX_FORS_BYTES]; - unsigned char addr[SPX_ADDR_BYTES]; - unsigned char block[SPX_N]; - - unsigned char wots_pk[SPX_WOTS_PK_BYTES]; - - unsigned long long smlen; - unsigned long long mlen; - unsigned long long t[NTESTS+1]; - struct timespec start, stop; - double result; - int i; - - randombytes(m, SPX_MLEN); - randombytes(addr, SPX_ADDR_BYTES); - - printf("Parameters: n = %d, h = %d, d = %d, b = %d, k = %d, w = %d\n", - SPX_N, SPX_FULL_HEIGHT, SPX_D, SPX_FORS_HEIGHT, SPX_FORS_TREES, - SPX_WOTS_W); - - printf("Running %d iterations.\n", NTESTS); - - MEASURT("thash ", 1, thash(block, block, 1, &ctx, (uint32_t*)addr)); - MEASURE("Generating keypair.. ", 1, crypto_sign_keypair(pk, sk)); - MEASURE(" - WOTS pk gen.. ", (1 << SPX_TREE_HEIGHT), wots_gen_pkx1(wots_pk, &ctx, (uint32_t *) addr)); - MEASURE("Signing.. ", 1, crypto_sign(sm, &smlen, m, SPX_MLEN, sk)); - MEASURE(" - FORS signing.. ", 1, fors_sign(fors_sig, fors_pk, fors_m, &ctx, (uint32_t *) addr)); - MEASURE(" - WOTS pk gen.. ", SPX_D * (1 << SPX_TREE_HEIGHT), wots_gen_pkx1(wots_pk, &ctx, (uint32_t *) addr)); - MEASURE("Verifying.. ", 1, crypto_sign_open(mout, &mlen, sm, smlen, pk)); - - printf("Signature size: %d (%.2f KiB)\n", SPX_BYTES, SPX_BYTES / 1024.0); - printf("Public key size: %d (%.2f KiB)\n", SPX_PK_BYTES, SPX_PK_BYTES / 1024.0); - printf("Secret key size: %d (%.2f KiB)\n", SPX_SK_BYTES, SPX_SK_BYTES / 1024.0); - - free(m); - free(sm); - free(mout); - - return 0; -} - -static void wots_gen_pkx1(unsigned char *pk, const spx_ctx *ctx, - uint32_t addr[8]) { - struct leaf_info_x1 leaf; - unsigned steps[ SPX_WOTS_LEN ] = { 0 }; - INITIALIZE_LEAF_INFO_X1(leaf, addr, steps); - wots_gen_leafx1(pk, ctx, 0, &leaf); -} - diff --git a/sphincsplus/ref/test/cycles.c b/sphincsplus/ref/test/cycles.c deleted file mode 100644 index 0fa46b5..0000000 --- a/sphincsplus/ref/test/cycles.c +++ /dev/null @@ -1,110 +0,0 @@ -#include "cycles.h" - -#if defined(__aarch64__) && defined(__APPLE__) -// Adapted from -// https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2021/03/24/ - -#include -#include -#include -#include - -#define KPERF_LIST \ - F(int, kpc_force_all_ctrs_set, int) \ - F(int, kpc_set_counting, uint32_t) \ - F(int, kpc_set_thread_counting, uint32_t) \ - F(int, kpc_set_config, uint32_t, void *) \ - F(uint32_t, kpc_get_counter_count, uint32_t) \ - F(uint32_t, kpc_get_config_count, uint32_t) \ - F(int, kpc_get_thread_counters, int, unsigned int, void *) - -#define F(ret, name, ...) \ - typedef ret name##proc(__VA_ARGS__); \ - static name##proc *name; -KPERF_LIST -#undef F - -uint64_t g_counters[10]; -uint64_t g_config[10]; - -static void configure_rdtsc(void) { - if (kpc_set_config(3, g_config)) { - printf("kpc_set_config failed\n"); - return; - } - - if (kpc_force_all_ctrs_set(1)) { - printf("kpc_force_all_ctrs_set failed\n"); - return; - } - - if (kpc_set_counting(3)) { - printf("kpc_set_counting failed\n"); - return; - } - - if (kpc_set_thread_counting(3)) { - printf("kpc_set_thread_counting failed\n"); - return; - } -} - -void init_cpucycles(void) { - void *kperf = dlopen( - "/System/Library/PrivateFrameworks/kperf.framework/Versions/A/kperf", - RTLD_LAZY); - if (!kperf) { - printf("kperf = %p\n", kperf); - return; - } -#define F(ret, name, ...) \ - name = (name##proc *)(dlsym(kperf, #name)); \ - if (!name) { \ - printf("%s = %p\n", #name, (void *)name); \ - return; \ - } - KPERF_LIST -#undef F - - if (kpc_get_counter_count(3) != 10) { - printf("wrong fixed counters count\n"); - return; - } - - if (kpc_get_config_count(3) != 8) { - printf("wrong fixed config count\n"); - return; - } - g_config[0] = 0x02 | 0x20000; - g_config[3] = 0x8d | 0x20000; - g_config[4] = 0xcb | 0x20000; - g_config[5] = 0x8c | 0x20000; - - configure_rdtsc(); -} - -unsigned long long cpucycles(void) { - static int warned = 0; - if (kpc_get_thread_counters(0, 10, g_counters)) { - if (!warned) { - printf("kpc_get_thread_counters failed, run as sudo?\n"); - warned = 1; - } - return 1; - } - // g_counters[3 + 2] gives you the number of instructions 'decoded' - // whereas g_counters[1] might give you the number of instructions 'retired'. - return g_counters[0 + 2]; -} -#else -void init_cpucycles(void) { -} - -unsigned long long cpucycles(void) -{ - unsigned long long result; - __asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax" - : "=a" (result) :: "%rdx"); - return result; -} -#endif diff --git a/sphincsplus/ref/test/fors.c b/sphincsplus/ref/test/fors.c deleted file mode 100644 index 73c828d..0000000 --- a/sphincsplus/ref/test/fors.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include - -#include "../context.h" -#include "../hash.h" -#include "../fors.h" -#include "../randombytes.h" -#include "../params.h" - -int main(void) -{ - /* Make stdout buffer more responsive. */ - setbuf(stdout, NULL); - - spx_ctx ctx; - - unsigned char pk1[SPX_FORS_PK_BYTES]; - unsigned char pk2[SPX_FORS_PK_BYTES]; - unsigned char sig[SPX_FORS_BYTES]; - unsigned char m[SPX_FORS_MSG_BYTES]; - uint32_t addr[8] = {0}; - - randombytes(ctx.sk_seed, SPX_N); - randombytes(ctx.pub_seed, SPX_N); - randombytes(m, SPX_FORS_MSG_BYTES); - randombytes((unsigned char *)addr, 8 * sizeof(uint32_t)); - - printf("Testing FORS signature and PK derivation.. "); - - initialize_hash_function(&ctx); - - fors_sign(sig, pk1, m, &ctx, addr); - fors_pk_from_sig(pk2, sig, m, &ctx, addr); - - if (memcmp(pk1, pk2, SPX_FORS_PK_BYTES)) { - printf("failed!\n"); - return -1; - } - printf("successful.\n"); - return 0; -} diff --git a/sphincsplus/ref/test/haraka.c b/sphincsplus/ref/test/haraka.c deleted file mode 100644 index 927d0de..0000000 --- a/sphincsplus/ref/test/haraka.c +++ /dev/null @@ -1,155 +0,0 @@ -#include -#include -#include -#include - -#include "../haraka.c" -#include "../randombytes.h" - -static int test_haraka_S_incremental(void) { - unsigned char input[521]; - unsigned char check[521]; - unsigned char output[521]; - uint8_t s_inc_absorb[65]; - uint8_t s_inc_squeeze[65]; - uint8_t s_inc_squeeze_all[65]; - uint8_t s_inc_both[65]; - uint8_t s_combined[64]; - int i; - int absorbed; - int squeezed; - int returncode = 0; - - randombytes(input, 521); - - haraka_S(check, 521, input, 521); - - haraka_S_inc_init(s_inc_absorb); - - absorbed = 0; - for (i = 0; i < 521 && absorbed + i <= 521; i++) { - haraka_S_inc_absorb(s_inc_absorb, input + absorbed, i); - absorbed += i; - } - haraka_S_inc_absorb(s_inc_absorb, input + absorbed, 521 - absorbed); - - haraka_S_inc_finalize(s_inc_absorb); - - memset(s_combined, 0, 64); - haraka_S_absorb(s_combined, HARAKAS_RATE, input, 521, 0x1F); - - if (memcmp(s_inc_absorb, s_combined, 64 * sizeof(uint8_t))) { - printf("ERROR haraka_S state after incremental absorb did not match all-at-once absorb.\n"); - printf(" Expected: "); - for (i = 0; i < 64; i++) { - printf("%02X", s_combined[i]); - } - printf("\n"); - printf(" State: "); - for (i = 0; i < 64; i++) { - printf("%02X", s_inc_absorb[i]); - } - printf("\n"); - returncode = 1; - } - - memcpy(s_inc_both, s_inc_absorb, 65 * sizeof(uint8_t)); - - haraka_S_squeezeblocks(output, 3, s_inc_absorb, HARAKAS_RATE); - - if (memcmp(check, output, 3*HARAKAS_RATE)) { - printf("ERROR haraka_S incremental absorb did not match haraka_S.\n"); - printf(" Expected: "); - for (i = 0; i < 3*HARAKAS_RATE; i++) { - printf("%02X", check[i]); - } - printf("\n"); - printf(" Received: "); - for (i = 0; i < 3*HARAKAS_RATE; i++) { - printf("%02X", output[i]); - } - printf("\n"); - returncode = 1; - } - - memset(s_inc_squeeze, 0, 65); - haraka_S_absorb(s_inc_squeeze, HARAKAS_RATE, input, 521, 0x1F); - s_inc_squeeze[64] = 0; - - memcpy(s_inc_squeeze_all, s_inc_squeeze, 65 * sizeof(uint8_t)); - - haraka_S_inc_squeeze(output, 521, s_inc_squeeze_all); - - if (memcmp(check, output, 521)) { - printf("ERROR haraka_S incremental squeeze-all did not match haraka_S.\n"); - printf(" Expected: "); - for (i = 0; i < 521; i++) { - printf("%02X", check[i]); - } - printf("\n"); - printf(" Received: "); - for (i = 0; i < 521; i++) { - printf("%02X", output[i]); - } - printf("\n"); - returncode = 1; - } - - squeezed = 0; - memset(output, 0, 521); - for (i = 0; i < 521 && squeezed + i <= 521; i++) { - haraka_S_inc_squeeze(output + squeezed, i, s_inc_squeeze); - squeezed += i; - } - haraka_S_inc_squeeze(output + squeezed, 521 - squeezed, s_inc_squeeze); - - if (memcmp(check, output, 521)) { - printf("ERROR haraka_S incremental squeeze did not match haraka_S.\n"); - printf(" Expected: "); - for (i = 0; i < 521; i++) { - printf("%02X", check[i]); - } - printf("\n"); - printf(" Received: "); - for (i = 0; i < 521; i++) { - printf("%02X", output[i]); - } - printf("\n"); - returncode = 1; - } - - squeezed = 0; - memset(output, 0, 521); - for (i = 0; i < 521 && squeezed + i <= 521; i++) { - haraka_S_inc_squeeze(output + squeezed, i, s_inc_both); - squeezed += i; - } - haraka_S_inc_squeeze(output + squeezed, 521 - squeezed, s_inc_both); - - if (memcmp(check, output, 521)) { - printf("ERROR haraka_S incremental absorb + squeeze did not match haraka_S.\n"); - printf(" Expected: "); - for (i = 0; i < 521; i++) { - printf("%02X", check[i]); - } - printf("\n"); - printf(" Received: "); - for (i = 0; i < 521; i++) { - printf("%02X", output[i]); - } - printf("\n"); - returncode = 1; - } - - return returncode; -} - -int main(void) { - int result = 0; - result += test_haraka_S_incremental(); - - if (result != 0) { - puts("Errors occurred"); - } - return result; -} diff --git a/sphincsplus/ref/test/spx.c b/sphincsplus/ref/test/spx.c deleted file mode 100644 index 2b214b9..0000000 --- a/sphincsplus/ref/test/spx.c +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include -#include - -#include "../api.h" -#include "../params.h" -#include "../randombytes.h" - -#define SPX_MLEN 32 -#define SPX_SIGNATURES 1 - -int main(void) -{ - int ret = 0; - int i; - - /* Make stdout buffer more responsive. */ - setbuf(stdout, NULL); - - unsigned char pk[SPX_PK_BYTES]; - unsigned char sk[SPX_SK_BYTES]; - unsigned char *m = malloc(SPX_MLEN); - unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); - unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); - unsigned long long smlen; - unsigned long long mlen; - - randombytes(m, SPX_MLEN); - - printf("Generating keypair.. "); - - if (crypto_sign_keypair(pk, sk)) { - printf("failed!\n"); - return -1; - } - printf("successful.\n"); - - printf("Testing %d signatures.. \n", SPX_SIGNATURES); - - for (i = 0; i < SPX_SIGNATURES; i++) { - printf(" - iteration #%d:\n", i); - - crypto_sign(sm, &smlen, m, SPX_MLEN, sk); - - if (smlen != SPX_BYTES + SPX_MLEN) { - printf(" X smlen incorrect [%llu != %u]!\n", - smlen, SPX_BYTES); - ret = -1; - } - else { - printf(" smlen as expected [%llu].\n", smlen); - } - - /* Test if signature is valid. */ - if (crypto_sign_open(mout, &mlen, sm, smlen, pk)) { - printf(" X verification failed!\n"); - ret = -1; - } - else { - printf(" verification succeeded.\n"); - } - - /* Test if the correct message was recovered. */ - if (mlen != SPX_MLEN) { - printf(" X mlen incorrect [%llu != %u]!\n", mlen, SPX_MLEN); - ret = -1; - } - else { - printf(" mlen as expected [%llu].\n", mlen); - } - if (memcmp(m, mout, SPX_MLEN)) { - printf(" X output message incorrect!\n"); - ret = -1; - } - else { - printf(" output message as expected.\n"); - } - - /* Test if signature is valid when validating in-place. */ - if (crypto_sign_open(sm, &mlen, sm, smlen, pk)) { - printf(" X in-place verification failed!\n"); - ret = -1; - } - else { - printf(" in-place verification succeeded.\n"); - } - - /* Test if flipping bits invalidates the signature (it should). */ - - /* Flip the first bit of the message. Should invalidate. */ - sm[smlen - 1] ^= 1; - if (!crypto_sign_open(mout, &mlen, sm, smlen, pk)) { - printf(" X flipping a bit of m DID NOT invalidate signature!\n"); - ret = -1; - } - else { - printf(" flipping a bit of m invalidates signature.\n"); - } - sm[smlen - 1] ^= 1; - -#ifdef SPX_TEST_INVALIDSIG - int j; - /* Flip one bit per hash; the signature is entirely hashes. */ - for (j = 0; j < (int)(smlen - SPX_MLEN); j += SPX_N) { - sm[j] ^= 1; - if (!crypto_sign_open(mout, &mlen, sm, smlen, pk)) { - printf(" X flipping bit %d DID NOT invalidate sig + m!\n", j); - sm[j] ^= 1; - ret = -1; - break; - } - sm[j] ^= 1; - } - if (j >= (int)(smlen - SPX_MLEN)) { - printf(" changing any signature hash invalidates signature.\n"); - } -#endif - } - - free(m); - free(sm); - free(mout); - - return ret; -} diff --git a/sphincsplus/ref/thash.h b/sphincsplus/ref/thash.h deleted file mode 100644 index 8687ccf..0000000 --- a/sphincsplus/ref/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/sphincsplus/ref/thash_haraka_robust.c b/sphincsplus/ref/thash_haraka_robust.c deleted file mode 100644 index 005e14a..0000000 --- a/sphincsplus/ref/thash_haraka_robust.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include - -#include "thash.h" -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) -{ - SPX_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(uint8_t, bitmask, inblocks*SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks*SPX_N, ctx); - } -} diff --git a/sphincsplus/ref/thash_haraka_simple.c b/sphincsplus/ref/thash_haraka_simple.c deleted file mode 100644 index 1040297..0000000 --- a/sphincsplus/ref/thash_haraka_simple.c +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include - -#include "thash.h" -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) -{ - SPX_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks*SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks*SPX_N, ctx); - } -} diff --git a/sphincsplus/ref/thash_sha2_robust.c b/sphincsplus/ref/thash_sha2_robust.c deleted file mode 100644 index 67ca3da..0000000 --- a/sphincsplus/ref/thash_sha2_robust.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "thash.h" -#include "address.h" -#include "params.h" -#include "utils.h" -#include "sha2.h" - -#if SPX_SHA512 -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); -#endif - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) -{ -#if SPX_SHA512 - if (inblocks > 1) { - thash_512(out, in, inblocks, ctx, addr); - return; - } -#endif - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - SPX_VLA(uint8_t, bitmask, inblocks * SPX_N); - SPX_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks*SPX_N); - uint8_t sha2_state[40]; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, ctx->state_seeded, 40 * sizeof(uint8_t)); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); - memcpy(out, outbuf, SPX_N); -} - -#if SPX_SHA512 -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) -{ - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - SPX_VLA(uint8_t, bitmask, inblocks * SPX_N); - SPX_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); - uint8_t sha2_state[72]; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, ctx->state_seeded_512, 72 * sizeof(uint8_t)); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha512_inc_finalize(outbuf, sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); - memcpy(out, outbuf, SPX_N); -} -#endif diff --git a/sphincsplus/ref/thash_sha2_simple.c b/sphincsplus/ref/thash_sha2_simple.c deleted file mode 100644 index da58896..0000000 --- a/sphincsplus/ref/thash_sha2_simple.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "thash.h" -#include "address.h" -#include "params.h" -#include "utils.h" -#include "sha2.h" - -#if SPX_SHA512 -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); -#endif - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) -{ -#if SPX_SHA512 - if (inblocks > 1) { - thash_512(out, in, inblocks, ctx, addr); - return; - } -#endif - - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint8_t sha2_state[40]; - SPX_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); - - /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, ctx->state_seeded, 40 * sizeof(uint8_t)); - - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); - - sha256_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); - memcpy(out, outbuf, SPX_N); -} - -#if SPX_SHA512 -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) -{ - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint8_t sha2_state[72]; - SPX_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); - - /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, ctx->state_seeded_512, 72 * sizeof(uint8_t)); - - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); - - sha512_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); - memcpy(out, outbuf, SPX_N); -} -#endif diff --git a/sphincsplus/ref/thash_shake_robust.c b/sphincsplus/ref/thash_shake_robust.c deleted file mode 100644 index 3589fde..0000000 --- a/sphincsplus/ref/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) -{ - SPX_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); -} diff --git a/sphincsplus/ref/thash_shake_simple.c b/sphincsplus/ref/thash_shake_simple.c deleted file mode 100644 index 7ce5c55..0000000 --- a/sphincsplus/ref/thash_shake_simple.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include - -#include "thash.h" -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) -{ - SPX_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); -} diff --git a/sphincsplus/ref/utils.c b/sphincsplus/ref/utils.c deleted file mode 100644 index 63d52ee..0000000 --- a/sphincsplus/ref/utils.c +++ /dev/null @@ -1,154 +0,0 @@ -#include - -#include "utils.h" -#include "params.h" -#include "hash.h" -#include "thash.h" -#include "address.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) -{ - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) -{ - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) -{ - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8*(inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) -{ - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } - else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } - else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx* ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char* /* leaf */, - const spx_ctx* /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) -{ - SPX_VLA(uint8_t, stack, (tree_height+1)*SPX_N); - SPX_VLA(unsigned int, heights, tree_height+1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset*SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset-1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/sphincsplus/ref/utils.h b/sphincsplus/ref/utils.h deleted file mode 100644 index b13502c..0000000 --- a/sphincsplus/ref/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include -#include "params.h" -#include "context.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ -#ifdef _MSC_VER -/* MSVC defines _alloca in malloc.h */ -# include -/* Note: _malloca(), which is recommended over deprecated _alloca, - requires that you call _freea(). So we stick with _alloca */ -# define SPX_VLA(__t,__x,__s) __t *__x = (__t*)_alloca((__s)*sizeof(__t)) -#else -# define SPX_VLA(__t,__x,__s) __t __x[__s] -#endif - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx* ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char* /* leaf */, - const spx_ctx* ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/sphincsplus/ref/utilsx1.c b/sphincsplus/ref/utilsx1.c deleted file mode 100644 index f6a6700..0000000 --- a/sphincsplus/ref/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utils.h" -#include "utilsx1.h" -#include "params.h" -#include "thash.h" -#include "address.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx* ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char* /* Where to write the leaves */, - const spx_ctx* /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) -{ - /* This is where we keep the intermediate nodes */ - SPX_VLA(uint8_t, stack, tree_height*SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2*SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h=0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx/2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/sphincsplus/ref/utilsx1.h b/sphincsplus/ref/utilsx1.h deleted file mode 100644 index a7fcf15..0000000 --- a/sphincsplus/ref/utilsx1.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include -#include "params.h" -#include "context.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx* ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char* /* Where to write the leaf */, - const spx_ctx* /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/sphincsplus/ref/wots.c b/sphincsplus/ref/wots.c deleted file mode 100644 index df83278..0000000 --- a/sphincsplus/ref/wots.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include - -#include "utils.h" -#include "utilsx1.h" -#include "hash.h" -#include "thash.h" -#include "wots.h" -#include "wotsx1.h" -#include "address.h" -#include "params.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) -{ - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start+steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) -{ - int in = 0; - int out = 0; - unsigned char total; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) -{ - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) -{ - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) -{ - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i*SPX_N, sig + i*SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/sphincsplus/ref/wots.h b/sphincsplus/ref/wots.h deleted file mode 100644 index 7e77056..0000000 --- a/sphincsplus/ref/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "params.h" -#include "context.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/sphincsplus/ref/wotsx1.c b/sphincsplus/ref/wotsx1.c deleted file mode 100644 index dfb3780..0000000 --- a/sphincsplus/ref/wotsx1.c +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include - -#include "utils.h" -#include "hash.h" -#include "thash.h" -#include "wots.h" -#include "wotsx1.h" -#include "address.h" -#include "params.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k=0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) break; - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/sphincsplus/ref/wotsx1.h b/sphincsplus/ref/wotsx1.h deleted file mode 100644 index 1257f81..0000000 --- a/sphincsplus/ref/wotsx1.h +++ /dev/null @@ -1,36 +0,0 @@ -#if !defined( WOTSX1_H_ ) -#define WOTSX1_H_ - -#include - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - info.wots_sig = 0; \ - info.wots_sign_leaf = ~0u; \ - info.wots_steps = step_buffer; \ - memcpy( &info.leaf_addr[0], addr, 32 ); \ - memcpy( &info.pk_addr[0], addr, 32 ); \ -} - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/sphincsplus/sha2-avx2/.gitignore b/sphincsplus/sha2-avx2/.gitignore deleted file mode 100644 index 20d83ac..0000000 --- a/sphincsplus/sha2-avx2/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -test/* -!test/*.c -PQCsignKAT_*.rsp -PQCsignKAT_*.req -PQCgenKAT_sign -keccak4x/KeccakP-1600-times4-SIMD256.o \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/Makefile b/sphincsplus/sha2-avx2/Makefile deleted file mode 100644 index f708543..0000000 --- a/sphincsplus/sha2-avx2/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -PARAMS = sphincs-sha2-128f -THASH = robust - -CC = /usr/bin/gcc -CFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3 -std=c99 -march=native -flto -fomit-frame-pointer -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) - - -SOURCES = hash_sha2.c hash_sha2x8.c thash_sha2_$(THASH).c thash_sha2_$(THASH)x8.c sha2.c sha256x8.c sha512x4.c sha256avx.c address.c randombytes.c merkle.c wots.c utils.c utilsx8.c fors.c sign.c -HEADERS = params.h hash.h hashx8.h thash.h thashx8.h sha2.h sha256x8.h sha512x4.h sha256avx.h address.h randombytes.h merkle.h wots.h utils.h utilsx8.h fors.h api.h - -DET_SOURCES = $(SOURCES:randombytes.%=rng.%) -DET_HEADERS = $(HEADERS:randombytes.%=rng.%) - -TESTS = test/fors \ - test/spx \ - test/thashx8 \ - -BENCHMARK = test/benchmark - -.PHONY: clean test benchmark - -default: PQCgenKAT_sign - -all: PQCgenKAT_sign tests benchmarks - -tests: $(TESTS) - -test: $(TESTS:=.exec) - -benchmarks: $(BENCHMARK) - -benchmark: $(BENCHMARK:=.exec) - -PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) - $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto - -test/%: test/%.c $(SOURCES) $(HEADERS) - $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) - -test/%.exec: test/% - @$< - -clean: - -$(RM) $(TESTS) - -$(RM) $(BENCHMARK) - -$(RM) PQCgenKAT_sign - -$(RM) PQCsignKAT_*.rsp - -$(RM) PQCsignKAT_*.req diff --git a/sphincsplus/sha2-avx2/PQCgenKAT_sign.c b/sphincsplus/sha2-avx2/PQCgenKAT_sign.c deleted file mode 120000 index a17dbe2..0000000 --- a/sphincsplus/sha2-avx2/PQCgenKAT_sign.c +++ /dev/null @@ -1 +0,0 @@ -../ref/PQCgenKAT_sign.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/address.c b/sphincsplus/sha2-avx2/address.c deleted file mode 120000 index 02c52c6..0000000 --- a/sphincsplus/sha2-avx2/address.c +++ /dev/null @@ -1 +0,0 @@ -../ref/address.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/address.h b/sphincsplus/sha2-avx2/address.h deleted file mode 120000 index e670da5..0000000 --- a/sphincsplus/sha2-avx2/address.h +++ /dev/null @@ -1 +0,0 @@ -../ref/address.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/api.h b/sphincsplus/sha2-avx2/api.h deleted file mode 120000 index ea89e0a..0000000 --- a/sphincsplus/sha2-avx2/api.h +++ /dev/null @@ -1 +0,0 @@ -../ref/api.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/context.h b/sphincsplus/sha2-avx2/context.h deleted file mode 100644 index 05ffbe8..0000000 --- a/sphincsplus/sha2-avx2/context.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - uint8_t state_seeded[40]; -#if SPX_SHA512 - uint8_t state_seeded_512[72]; -#endif -} spx_ctx; - -#endif diff --git a/sphincsplus/sha2-avx2/fors.c b/sphincsplus/sha2-avx2/fors.c deleted file mode 100644 index 67ad322..0000000 --- a/sphincsplus/sha2-avx2/fors.c +++ /dev/null @@ -1,233 +0,0 @@ -#include -#include -#include - -#include "fors.h" -#include "utils.h" -#include "utilsx8.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "address.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) -{ - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8*8]) -{ - prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - ctx, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) -{ - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8*8]) -{ - thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - 1, ctx, fors_leaf_addrx8); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8*8]; -}; - -static void fors_gen_leafx8(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) -{ - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 8; j++) { - set_tree_index(fors_leaf_addrx8 + j*8, addr_idx + j); - set_type(fors_leaf_addrx8 + j*8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx8(leaf + 0*SPX_N, - leaf + 1*SPX_N, - leaf + 2*SPX_N, - leaf + 3*SPX_N, - leaf + 4*SPX_N, - leaf + 5*SPX_N, - leaf + 6*SPX_N, - leaf + 7*SPX_N, - ctx, fors_leaf_addrx8); - - for (j = 0; j < 8; j++) { - set_type(fors_leaf_addrx8 + j*8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx8(leaf + 0*SPX_N, - leaf + 1*SPX_N, - leaf + 2*SPX_N, - leaf + 3*SPX_N, - leaf + 4*SPX_N, - leaf + 5*SPX_N, - leaf + 6*SPX_N, - leaf + 7*SPX_N, - leaf + 0*SPX_N, - leaf + 1*SPX_N, - leaf + 2*SPX_N, - leaf + 3*SPX_N, - leaf + 4*SPX_N, - leaf + 5*SPX_N, - leaf + 6*SPX_N, - leaf + 7*SPX_N, - ctx, fors_leaf_addrx8); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) -{ - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= ((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) -{ - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8*8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i=0; i<8; i++) { - copy_keypair_addr(fors_tree_addr + 8*i, fors_addr); - set_type(fors_tree_addr + 8*i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8*i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx8(roots + i*SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) -{ - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i*SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/sphincsplus/sha2-avx2/fors.h b/sphincsplus/sha2-avx2/fors.h deleted file mode 120000 index 07156bd..0000000 --- a/sphincsplus/sha2-avx2/fors.h +++ /dev/null @@ -1 +0,0 @@ -../ref/fors.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/hash.h b/sphincsplus/sha2-avx2/hash.h deleted file mode 120000 index cffc52b..0000000 --- a/sphincsplus/sha2-avx2/hash.h +++ /dev/null @@ -1 +0,0 @@ -../ref/hash.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/hash_sha2.c b/sphincsplus/sha2-avx2/hash_sha2.c deleted file mode 120000 index cfd85d4..0000000 --- a/sphincsplus/sha2-avx2/hash_sha2.c +++ /dev/null @@ -1 +0,0 @@ -../ref/hash_sha2.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/hash_sha2x8.c b/sphincsplus/sha2-avx2/hash_sha2x8.c deleted file mode 100644 index 3f59b9a..0000000 --- a/sphincsplus/sha2-avx2/hash_sha2x8.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "utils.h" -#include "params.h" -#include "hashx8.h" -#include "sha2.h" -#include "sha256x8.h" -#include "sha256avx.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8*8]) -{ - unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j*(SPX_N + SPX_SHA256_ADDR_BYTES), - addrx8 + j*8, SPX_SHA256_ADDR_BYTES); - memcpy( - bufx8 + j*(SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, - ctx->sk_seed, - SPX_N - ); - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - ctx->state_seeded, 512, - - /* in */ - bufx8 + 0*(SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 1*(SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 2*(SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 3*(SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 4*(SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 5*(SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 6*(SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 7*(SPX_SHA256_ADDR_BYTES + SPX_N), - SPX_SHA256_ADDR_BYTES + SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, SPX_N); -} diff --git a/sphincsplus/sha2-avx2/hashx8.h b/sphincsplus/sha2-avx2/hashx8.h deleted file mode 100644 index dc924b4..0000000 --- a/sphincsplus/sha2-avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_HASHX8_H -#define SPX_HASHX8_H - -#include -#include "params.h" - -#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8*8]); - -#endif diff --git a/sphincsplus/sha2-avx2/merkle.c b/sphincsplus/sha2-avx2/merkle.c deleted file mode 100644 index 0b3f666..0000000 --- a/sphincsplus/sha2-avx2/merkle.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include "utils.h" -#include "utilsx8.h" -#include "wots.h" -#include "wotsx8.h" -#include "wotsx8.h" -#include "merkle.h" -#include "address.h" -#include "params.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) -{ - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx8[8*8] = { 0 }; - int j; - struct leaf_info_x8 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j=0; j<8; j++) { - set_type(&tree_addrx8[8*j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8*j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8*j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx8[8*j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8*j], wots_addr); - copy_subtree_addr(&info.pk_addr[8*j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx8(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx8, - tree_addrx8, &info); -} - -/* Compute root node of the top-most subtree. */ -/* Again, in this file because wots_gen_leaf is most of the work */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) -{ - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/sphincsplus/sha2-avx2/merkle.h b/sphincsplus/sha2-avx2/merkle.h deleted file mode 120000 index 7d167ed..0000000 --- a/sphincsplus/sha2-avx2/merkle.h +++ /dev/null @@ -1 +0,0 @@ -../ref/merkle.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/params.h b/sphincsplus/sha2-avx2/params.h deleted file mode 120000 index 53133cc..0000000 --- a/sphincsplus/sha2-avx2/params.h +++ /dev/null @@ -1 +0,0 @@ -../ref/params.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-128f.h b/sphincsplus/sha2-avx2/params/params-sphincs-sha2-128f.h deleted file mode 120000 index d901a75..0000000 --- a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-128f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-sha2-128f.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-128s.h b/sphincsplus/sha2-avx2/params/params-sphincs-sha2-128s.h deleted file mode 120000 index a9955de..0000000 --- a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-128s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-sha2-128s.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-192f.h b/sphincsplus/sha2-avx2/params/params-sphincs-sha2-192f.h deleted file mode 120000 index ecbc980..0000000 --- a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-192f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-sha2-192f.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-192s.h b/sphincsplus/sha2-avx2/params/params-sphincs-sha2-192s.h deleted file mode 120000 index c2db1ba..0000000 --- a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-192s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-sha2-192s.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-256f.h b/sphincsplus/sha2-avx2/params/params-sphincs-sha2-256f.h deleted file mode 120000 index b388615..0000000 --- a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-256f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-sha2-256f.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-256s.h b/sphincsplus/sha2-avx2/params/params-sphincs-sha2-256s.h deleted file mode 120000 index 420ffec..0000000 --- a/sphincsplus/sha2-avx2/params/params-sphincs-sha2-256s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-sha2-256s.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/randombytes.c b/sphincsplus/sha2-avx2/randombytes.c deleted file mode 120000 index 59a42a5..0000000 --- a/sphincsplus/sha2-avx2/randombytes.c +++ /dev/null @@ -1 +0,0 @@ -../ref/randombytes.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/randombytes.h b/sphincsplus/sha2-avx2/randombytes.h deleted file mode 120000 index 055e443..0000000 --- a/sphincsplus/sha2-avx2/randombytes.h +++ /dev/null @@ -1 +0,0 @@ -../ref/randombytes.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/rng.c b/sphincsplus/sha2-avx2/rng.c deleted file mode 120000 index 6e2fdac..0000000 --- a/sphincsplus/sha2-avx2/rng.c +++ /dev/null @@ -1 +0,0 @@ -../ref/rng.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/rng.h b/sphincsplus/sha2-avx2/rng.h deleted file mode 120000 index d678c7c..0000000 --- a/sphincsplus/sha2-avx2/rng.h +++ /dev/null @@ -1 +0,0 @@ -../ref/rng.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/sha2.c b/sphincsplus/sha2-avx2/sha2.c deleted file mode 120000 index 7ba32d4..0000000 --- a/sphincsplus/sha2-avx2/sha2.c +++ /dev/null @@ -1 +0,0 @@ -../ref/sha2.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/sha2.h b/sphincsplus/sha2-avx2/sha2.h deleted file mode 120000 index 8c1ff67..0000000 --- a/sphincsplus/sha2-avx2/sha2.h +++ /dev/null @@ -1 +0,0 @@ -../ref/sha2.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/sha256avx.c b/sphincsplus/sha2-avx2/sha256avx.c deleted file mode 100644 index 7fc1091..0000000 --- a/sphincsplus/sha2-avx2/sha256avx.c +++ /dev/null @@ -1,294 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void sha256_init8x(sha256ctx *ctx) { - ctx->s[0] = _mm256_set_epi32(0x6a09e667,0x6a09e667,0x6a09e667,0x6a09e667,0x6a09e667,0x6a09e667,0x6a09e667,0x6a09e667); - ctx->s[1] = _mm256_set_epi32(0xbb67ae85,0xbb67ae85,0xbb67ae85,0xbb67ae85,0xbb67ae85,0xbb67ae85,0xbb67ae85,0xbb67ae85); - ctx->s[2] = _mm256_set_epi32(0x3c6ef372,0x3c6ef372,0x3c6ef372,0x3c6ef372,0x3c6ef372,0x3c6ef372,0x3c6ef372,0x3c6ef372); - ctx->s[3] = _mm256_set_epi32(0xa54ff53a,0xa54ff53a,0xa54ff53a,0xa54ff53a,0xa54ff53a,0xa54ff53a,0xa54ff53a,0xa54ff53a); - ctx->s[4] = _mm256_set_epi32(0x510e527f,0x510e527f,0x510e527f,0x510e527f,0x510e527f,0x510e527f,0x510e527f,0x510e527f); - ctx->s[5] = _mm256_set_epi32(0x9b05688c,0x9b05688c,0x9b05688c,0x9b05688c,0x9b05688c,0x9b05688c,0x9b05688c,0x9b05688c); - ctx->s[6] = _mm256_set_epi32(0x1f83d9ab,0x1f83d9ab,0x1f83d9ab,0x1f83d9ab,0x1f83d9ab,0x1f83d9ab,0x1f83d9ab,0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32(0x5be0cd19,0x5be0cd19,0x5be0cd19,0x5be0cd19,0x5be0cd19,0x5be0cd19,0x5be0cd19,0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void sha256_final8x(sha256ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) -{ - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64*i + curlen++] = 0x80; - while(curlen < 64) { - ctx->msgblocks[64*i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64*i + curlen++] = 0x80; - while(curlen < 64) { - ctx->msgblocks[64*i + curlen++] = 0x00; - } - } - sha256_transform8x(ctx, - &ctx->msgblocks[64*0], - &ctx->msgblocks[64*1], - &ctx->msgblocks[64*2], - &ctx->msgblocks[64*3], - &ctx->msgblocks[64*4], - &ctx->msgblocks[64*5], - &ctx->msgblocks[64*6], - &ctx->msgblocks[64*7] - ); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64*i + 63] = ctx->msglen; - ctx->msgblocks[64*i + 62] = ctx->msglen >> 8; - ctx->msgblocks[64*i + 61] = ctx->msglen >> 16; - ctx->msgblocks[64*i + 60] = ctx->msglen >> 24; - ctx->msgblocks[64*i + 59] = ctx->msglen >> 32; - ctx->msgblocks[64*i + 58] = ctx->msglen >> 40; - ctx->msgblocks[64*i + 57] = ctx->msglen >> 48; - ctx->msgblocks[64*i + 56] = ctx->msglen >> 56; - } - sha256_transform8x(ctx, - &ctx->msgblocks[64*0], - &ctx->msgblocks[64*1], - &ctx->msgblocks[64*2], - &ctx->msgblocks[64*3], - &ctx->msgblocks[64*4], - &ctx->msgblocks[64*5], - &ctx->msgblocks[64*6], - &ctx->msgblocks[64*7] - ); - - // Compute final hash output - transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void sha256_transform8x(sha256ctx *ctx, - const unsigned char* data0, - const unsigned char* data1, - const unsigned char* data2, - const unsigned char* data3, - const unsigned char* data4, - const unsigned char* data5, - const unsigned char* data6, - const unsigned char* data7) { - u256 s[8], w[64], T0, T1; - - // Load words and transform data correctly - w[0] = BYTESWAP(LOAD(data0)); - w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); - w[1] = BYTESWAP(LOAD(data1)); - w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); - w[2] = BYTESWAP(LOAD(data2)); - w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); - w[3] = BYTESWAP(LOAD(data3)); - w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); - w[4] = BYTESWAP(LOAD(data4)); - w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); - w[5] = BYTESWAP(LOAD(data5)); - w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); - w[6] = BYTESWAP(LOAD(data6)); - w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); - w[7] = BYTESWAP(LOAD(data7)); - w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); - - transpose(w); - transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/sphincsplus/sha2-avx2/sha256avx.h b/sphincsplus/sha2-avx2/sha256avx.h deleted file mode 100644 index e887063..0000000 --- a/sphincsplus/sha2-avx2/sha256avx.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H -#include "immintrin.h" -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - y)) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - y)) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32(RC[rc]), w); \ - d = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - h = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - unsigned char msgblocks[8*64]; - int datalen; - unsigned long long msglen; -} sha256ctx; - - -void transpose(u256 s[8]); -void sha256_init8x(sha256ctx *ctx); -void sha256_final8x(sha256ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void sha256_transform8x(sha256ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7); - -#endif diff --git a/sphincsplus/sha2-avx2/sha256x8.c b/sphincsplus/sha2-avx2/sha256x8.c deleted file mode 100644 index 6f4f965..0000000 --- a/sphincsplus/sha2-avx2/sha256x8.c +++ /dev/null @@ -1,201 +0,0 @@ -#include - -#include "sha256x8.h" -#include "sha256avx.h" -#include "utils.h" - -static uint32_t load_bigendian_32(const uint8_t *x) { - return (uint32_t)(x[3]) | (((uint32_t)(x[2])) << 8) | - (((uint32_t)(x[1])) << 16) | (((uint32_t)(x[0])) << 24); -} - -// Performs sha256x8 on an initialized (and perhaps seeded) state. -static void _sha256x8( - sha256ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - unsigned long long i = 0; - while(inlen - i >= 64) { - sha256_transform8x(ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i, - in4 + i, - in5 + i, - in6 + i, - in7 + i - ); - i += 64; - ctx->msglen += 512; - } - - int bytes_to_copy = inlen - i; - memcpy(&ctx->msgblocks[64*0], in0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64*1], in1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64*2], in2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64*3], in3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64*4], in4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64*5], in5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64*6], in6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64*7], in7 + i, bytes_to_copy); - ctx->datalen = bytes_to_copy; - - sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *seed, - unsigned long long seedlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - uint32_t t; - - sha256ctx ctx; - - for (size_t i = 0; i < 8; i++) { - t = load_bigendian_32(seed + 4*i); - ctx.s[i] = _mm256_set_epi32(t, t, t, t, t, t, t, t); - } - - ctx.datalen = 0; - ctx.msglen = seedlen; - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) -{ - sha256ctx ctx; - sha256_init8x(&ctx); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) -{ - SPX_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); - unsigned char outbufx8[8*SPX_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0*(inlen + 4), in0, inlen); - memcpy(inbufx8 + 1*(inlen + 4), in1, inlen); - memcpy(inbufx8 + 2*(inlen + 4), in2, inlen); - memcpy(inbufx8 + 3*(inlen + 4), in3, inlen); - memcpy(inbufx8 + 4*(inlen + 4), in4, inlen); - memcpy(inbufx8 + 5*(inlen + 4), in5, inlen); - memcpy(inbufx8 + 6*(inlen + 4), in6, inlen); - memcpy(inbufx8 + 7*(inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i+1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j*(inlen + 4), i); - } - - sha256x8(outx8 + 0*outlen, - outx8 + 1*outlen, - outx8 + 2*outlen, - outx8 + 3*outlen, - outx8 + 4*outlen, - outx8 + 5*outlen, - outx8 + 6*outlen, - outx8 + 7*outlen, - inbufx8 + 0*(inlen + 4), - inbufx8 + 1*(inlen + 4), - inbufx8 + 2*(inlen + 4), - inbufx8 + 3*(inlen + 4), - inbufx8 + 4*(inlen + 4), - inbufx8 + 5*(inlen + 4), - inbufx8 + 6*(inlen + 4), - inbufx8 + 7*(inlen + 4), inlen + 4); - outx8 += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j*(inlen + 4), i); - } - sha256x8(outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, - inbufx8 + 0*(inlen + 4), - inbufx8 + 1*(inlen + 4), - inbufx8 + 2*(inlen + 4), - inbufx8 + 3*(inlen + 4), - inbufx8 + 4*(inlen + 4), - inbufx8 + 5*(inlen + 4), - inbufx8 + 6*(inlen + 4), - inbufx8 + 7*(inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j*outlen, - outbufx8 + j*SPX_SHA256_OUTPUT_BYTES, - outlen - i*SPX_SHA256_OUTPUT_BYTES); - } -} diff --git a/sphincsplus/sha2-avx2/sha256x8.h b/sphincsplus/sha2-avx2/sha256x8.h deleted file mode 100644 index 0060de5..0000000 --- a/sphincsplus/sha2-avx2/sha256x8.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef SPX_SHA256X8_H -#define SPX_SHA256X8_H - -#include "params.h" - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal SPX_N */ - -#if SPX_SHA256_OUTPUT_BYTES < SPX_N - #error Linking against SHA-256 with N larger than 32 bytes is not supported -#endif - -#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *seed, - unsigned long long seedlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -#define sha256x8 SPX_NAMESPACE(sha256x8) -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x8 SPX_NAMESPACE(mgf1x8) -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); -#endif diff --git a/sphincsplus/sha2-avx2/sha2_offsets.h b/sphincsplus/sha2-avx2/sha2_offsets.h deleted file mode 120000 index ca63278..0000000 --- a/sphincsplus/sha2-avx2/sha2_offsets.h +++ /dev/null @@ -1 +0,0 @@ -../ref/sha2_offsets.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/sha512x4.c b/sphincsplus/sha2-avx2/sha512x4.c deleted file mode 100644 index 3eaa0f6..0000000 --- a/sphincsplus/sha2-avx2/sha512x4.c +++ /dev/null @@ -1,462 +0,0 @@ -#include -#include -#include - -#define SPX_SHA512_OUTPUT_BYTES 64 /* In sha256.h, but we don't want to */ - /* pull in the entire thing */ -#include "sha512x4.h" -#include "utils.h" - -typedef uint64_t u64; -typedef __m256i u256; - -static void sha512_transform4x( - sha512ctx4x *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3 -); - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -// Transpose 4 vectors containing 64-bit values -// That is, it rearranges the array: -// A B C D -// E F G H -// I J K L -// M N O P -// into -// A E I M -// B F J N -// C G K O -// D H L P -// where each letter stands for 64 bits (and lsbits on the left) -static void transpose(u256 s[4]) { - u256 tmp[4]; - tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); - tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); - tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); - tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); - // tmp is in the order of - // A E C G - // B F D H - // I M K O - // J N L P - s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); - s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); - s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); - s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); -} - - -static void sha512_init4x(sha512ctx4x *ctx) { -#define SET4(x) _mm256_set_epi64x(x, x, x, x) - ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); - ctx->s[1] = SET4(0xbb67ae8584caa73bULL); - ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); - ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); - ctx->s[4] = SET4(0x510e527fade682d1ULL); - ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); - ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); - ctx->s[7] = SET4(0x5be0cd19137e2179ULL); -#undef SET4 - - ctx->datalen = 0; - ctx->msglen = 0; -} - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD64 _mm256_add_epi64 - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) - -#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) -#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) - -#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - y)) - -static u256 XOR3(u256 a, u256 b, u256 c) { - return XOR(XOR(a, b), c); -} - -#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) -#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) -#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) - -static u256 MAJ_AVX(u256 a, u256 b, u256 c) { - return XOR(c, AND(XOR(a, c), XOR(b, c))); -} -static u256 CH_AVX(u256 a, u256 b, u256 c) { - return XOR(c, AND(a, XOR(b, c))); -} -static u256 SIGMA0_AVX(u256 x) { - return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); -} -static u256 SIGMA1_AVX(u256 x) { - return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); -} -static u256 GAMMA0_AVX(u256 x) { - return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); -} -static u256 GAMMA1_AVX(u256 x) { - return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); -} - -#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x(RC[rc])); \ - T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - d = ADD64(d, T0); \ - h = ADD64(T0, T1); - -static const unsigned long long RC[80] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, - 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, - 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, - 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, - 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, - 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, - 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, - 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, - 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, - 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, - 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, - 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, - 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, - 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, - 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, - 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, - 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, - 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, - 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, - 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, - 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, - 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, - 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, - 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, - 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, - 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, - 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, -}; - -static void sha512_transform4x( - sha512ctx4x *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3) { - u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; - - // Load words and transform data correctly - w[0 ] = BYTESWAP(LOAD(d0 )); - w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); - w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); - w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); - - w[1 ] = BYTESWAP(LOAD(d1 )); - w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); - w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); - w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); - - w[2 ] = BYTESWAP(LOAD(d2 )); - w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); - w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); - w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); - - w[3 ] = BYTESWAP(LOAD(d3 )); - w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); - w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); - w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); - - transpose(w); - transpose(w + 4); - transpose(w + 8); - transpose(w + 12); - - // Initial State - s0 = ctx->s[0]; - s1 = ctx->s[1]; - s2 = ctx->s[2]; - s3 = ctx->s[3]; - s4 = ctx->s[4]; - s5 = ctx->s[5]; - s6 = ctx->s[6]; - s7 = ctx->s[7]; - - // The first 16 rounds (where the w inputs are directly from the data) - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); - -#define M(i) (((i)+16) & 0xf) -#define NextW(i) \ - w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); - - // The remaining 64 rounds (where the w inputs are a linear fix of the data) - for (unsigned i = 16; i<80; i+=16) { - nw = NextW(0); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i+0, nw); - nw = NextW(1); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i+1, nw); - nw = NextW(2); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i+2, nw); - nw = NextW(3); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i+3, nw); - nw = NextW(4); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i+4, nw); - nw = NextW(5); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i+5, nw); - nw = NextW(6); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i+6, nw); - nw = NextW(7); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i+7, nw); - nw = NextW(8); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i+8, nw); - nw = NextW(9); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i+9, nw); - nw = NextW(10); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i+10, nw); - nw = NextW(11); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i+11, nw); - nw = NextW(12); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i+12, nw); - nw = NextW(13); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i+13, nw); - nw = NextW(14); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i+14, nw); - nw = NextW(15); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i+15, nw); - } - - // Feed Forward - ctx->s[0] = ADD64(s0, ctx->s[0]); - ctx->s[1] = ADD64(s1, ctx->s[1]); - ctx->s[2] = ADD64(s2, ctx->s[2]); - ctx->s[3] = ADD64(s3, ctx->s[3]); - ctx->s[4] = ADD64(s4, ctx->s[4]); - ctx->s[5] = ADD64(s5, ctx->s[5]); - ctx->s[6] = ADD64(s6, ctx->s[6]); - ctx->s[7] = ADD64(s7, ctx->s[7]); -} - -static void _sha512x4( - sha512ctx4x* ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen) { - unsigned int i = 0; - - while(inlen - i >= 128) { - sha512_transform4x( - ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i - ); - ctx->msglen += 1024; - i += 128; - } - - ctx->datalen = inlen - i; - memcpy(&ctx->msgblocks[128*0], in0 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128*1], in1 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128*2], in2 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128*3], in3 + i, ctx->datalen); - - // Padding - unsigned long curlen; - if (ctx->datalen < 112) { - for (i = 0; i < 4; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[128*i + curlen++] = 0x80; - while(curlen < 128) { - ctx->msgblocks[128*i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 4; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[128*i + curlen++] = 0x80; - while(curlen < 128) { - ctx->msgblocks[128*i + curlen++] = 0x00; - } - } - sha512_transform4x( - ctx, - ctx->msgblocks, - ctx->msgblocks + 128, - ctx->msgblocks + 256, - ctx->msgblocks + 384 - ); - memset(ctx->msgblocks, 0, 4 * 128); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 4; i++) { - ctx->msgblocks[128*i + 127] = ctx->msglen; - ctx->msgblocks[128*i + 126] = ctx->msglen >> 8; - ctx->msgblocks[128*i + 125] = ctx->msglen >> 16; - ctx->msgblocks[128*i + 124] = ctx->msglen >> 24; - ctx->msgblocks[128*i + 123] = ctx->msglen >> 32; - ctx->msgblocks[128*i + 122] = ctx->msglen >> 40; - ctx->msgblocks[128*i + 121] = ctx->msglen >> 48; - ctx->msgblocks[128*i + 120] = ctx->msglen >> 56; - memset( &ctx->msgblocks[128*i + 112], 0, 8 ); - } - sha512_transform4x( - ctx, - ctx->msgblocks, - ctx->msgblocks + 128, - ctx->msgblocks + 256, - ctx->msgblocks + 384 - ); - - // Compute final hash output - transpose(ctx->s); - transpose(ctx->s+4); - - // Store Hash value - __m256i out[2]; - STORE(out, BYTESWAP(ctx->s[0])); - STORE(out+1, BYTESWAP(ctx->s[4])); - memcpy(out0, out, 64); - - STORE(out, BYTESWAP(ctx->s[1])); - STORE(out+1, BYTESWAP(ctx->s[5])); - memcpy(out1, out, 64); - - STORE(out, BYTESWAP(ctx->s[2])); - STORE(out+1, BYTESWAP(ctx->s[6])); - memcpy(out2, out, 64); - - STORE(out, BYTESWAP(ctx->s[3])); - STORE(out+1, BYTESWAP(ctx->s[7])); - memcpy(out3, out, 64); -} - - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x4_512(unsigned char *outx4, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long inlen) -{ - SPX_VLA(unsigned char, inbufx4, 4*(inlen + 4)); - unsigned char outbuf[4*64]; - unsigned long i; - unsigned int j; - - memcpy(inbufx4 + 0*(inlen + 4), in0, inlen); - memcpy(inbufx4 + 1*(inlen + 4), in1, inlen); - memcpy(inbufx4 + 2*(inlen + 4), in2, inlen); - memcpy(inbufx4 + 3*(inlen + 4), in3, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - unsigned long remaining = outlen; - for (i = 0; remaining > 0; i++) { - unsigned this_step = SPX_SHA512_OUTPUT_BYTES; - if (this_step > remaining) this_step = remaining; - remaining -= this_step; - for (j = 0; j < 4; j++) { - u32_to_bytes(inbufx4 + inlen + j*(inlen + 4), i); - } - - sha512ctx4x ctx; - sha512_init4x(&ctx); - - _sha512x4( - &ctx, - outbuf + 0*64, - outbuf + 1*64, - outbuf + 2*64, - outbuf + 3*64, - inbufx4 + 0*(inlen + 4), - inbufx4 + 1*(inlen + 4), - inbufx4 + 2*(inlen + 4), - inbufx4 + 3*(inlen + 4), - inlen+4 - ); - - memcpy(outx4 + 0*outlen, outbuf+0*64, this_step); - memcpy(outx4 + 1*outlen, outbuf+1*64, this_step); - memcpy(outx4 + 2*outlen, outbuf+2*64, this_step); - memcpy(outx4 + 3*outlen, outbuf+3*64, this_step); - outx4 += this_step; - } -} - -void sha512x4_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *seed, - unsigned long long seedlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen) { - sha512ctx4x ctx; - unsigned long i; - - for (i = 0; i < 8; i++) { - uint64_t t = (uint64_t)(seed[7]) | (((uint64_t)(seed[6])) << 8) | - (((uint64_t)(seed[5])) << 16) | (((uint64_t)(seed[4])) << 24) | - (((uint64_t)(seed[3])) << 32) | (((uint64_t)(seed[2])) << 40) | - (((uint64_t)(seed[1])) << 48) | (((uint64_t)(seed[0])) << 56); - ctx.s[i] = _mm256_set_epi64x(t, t, t, t); - seed += 8; - } - - ctx.msglen = seedlen; - _sha512x4( - &ctx, - out0, out1, out2, out3, - in0, in1, in2, in3, - inlen - ); -} diff --git a/sphincsplus/sha2-avx2/sha512x4.h b/sphincsplus/sha2-avx2/sha512x4.h deleted file mode 100644 index 013459f..0000000 --- a/sphincsplus/sha2-avx2/sha512x4.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef SHA512AVX_H -#define SHA512AVX_H -#include -#include "immintrin.h" - -#include "params.h" - -typedef struct SHA512state4x { - __m256i s[8]; - unsigned char msgblocks[4*128]; - int datalen; - unsigned long long msglen; -} sha512ctx4x; - - -#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) -void sha512x4_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *seed, - unsigned long long seedlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen); - - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) -void mgf1x4_512(unsigned char *outx4, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long inlen); - -#endif diff --git a/sphincsplus/sha2-avx2/sign.c b/sphincsplus/sha2-avx2/sign.c deleted file mode 120000 index 42fea88..0000000 --- a/sphincsplus/sha2-avx2/sign.c +++ /dev/null @@ -1 +0,0 @@ -../ref/sign.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/test/benchmark.c b/sphincsplus/sha2-avx2/test/benchmark.c deleted file mode 100644 index a65bd62..0000000 --- a/sphincsplus/sha2-avx2/test/benchmark.c +++ /dev/null @@ -1,162 +0,0 @@ -#define _POSIX_C_SOURCE 199309L - -#include -#include -#include - -#include "../api.h" -#include "../fors.h" -#include "../wots.h" -#include "../wotsx8.h" -#include "../params.h" -#include "../randombytes.h" - -#define SPX_MLEN 32 -#define NTESTS 10 - -static void wots_gen_pkx8(unsigned char *pk, const spx_ctx *ctx, - uint32_t addr[8]); - -static int cmp_llu(const void *a, const void*b) -{ - if(*(unsigned long long *)a < *(unsigned long long *)b) return -1; - if(*(unsigned long long *)a > *(unsigned long long *)b) return 1; - return 0; -} - -static unsigned long long median(unsigned long long *l, size_t llen) -{ - qsort(l,llen,sizeof(unsigned long long),cmp_llu); - - if(llen%2) return l[llen/2]; - else return (l[llen/2-1]+l[llen/2])/2; -} - -static void delta(unsigned long long *l, size_t llen) -{ - unsigned int i; - for(i = 0; i < llen - 1; i++) { - l[i] = l[i+1] - l[i]; - } -} - -static unsigned long long cpucycles(void) -{ - unsigned long long result; - __asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax" - : "=a" (result) :: "%rdx"); - return result; -} - -static void printfcomma (unsigned long long n) -{ - if (n < 1000) { - printf("%llu", n); - return; - } - printfcomma(n / 1000); - printf (",%03llu", n % 1000); -} - -static void printfalignedcomma (unsigned long long n, int len) -{ - unsigned long long ncopy = n; - int i = 0; - - while (ncopy > 9) { - len -= 1; - ncopy /= 10; - i += 1; // to account for commas - } - i = i/3 - 1; // to account for commas - for (; i < len; i++) { - printf(" "); - } - printfcomma(n); -} - -static void display_result(double result, unsigned long long *l, size_t llen, unsigned long long mul) -{ - unsigned long long med; - - result /= NTESTS; - delta(l, NTESTS + 1); - med = median(l, llen); - printf("avg. %11.2lf us (%2.2lf sec); median ", result, result / 1e6); - printfalignedcomma(med, 12); - printf(" cycles, %5llux: ", mul); - printfalignedcomma(mul*med, 12); - printf(" cycles\n"); -} - -#define MEASURE(TEXT, MUL, FNCALL)\ - printf(TEXT);\ - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);\ - for(i = 0; i < NTESTS; i++) {\ - t[i] = cpucycles();\ - FNCALL;\ - }\ - t[NTESTS] = cpucycles();\ - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop);\ - result = (stop.tv_sec - start.tv_sec) * 1e6 + (stop.tv_nsec - start.tv_nsec) / 1e3;\ - display_result(result, t, NTESTS, MUL); - -int main(void) -{ - /* Make stdout buffer more responsive. */ - setbuf(stdout, NULL); - - spx_ctx ctx; - unsigned char pk[SPX_PK_BYTES]; - unsigned char sk[SPX_SK_BYTES]; - unsigned char *m = malloc(SPX_MLEN); - unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); - unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); - - unsigned char fors_pk[SPX_FORS_PK_BYTES]; - unsigned char fors_m[SPX_FORS_MSG_BYTES]; - unsigned char fors_sig[SPX_FORS_BYTES]; - unsigned char addr[SPX_ADDR_BYTES]; - unsigned char wots_pk[8*SPX_WOTS_PK_BYTES]; - - unsigned long long smlen; - unsigned long long mlen; - unsigned long long t[NTESTS+1]; - struct timespec start, stop; - double result; - int i; - - randombytes(m, SPX_MLEN); - randombytes(addr, SPX_ADDR_BYTES); - - printf("Parameters: n = %d, h = %d, d = %d, b = %d, k = %d, w = %d\n", - SPX_N, SPX_FULL_HEIGHT, SPX_D, SPX_FORS_HEIGHT, SPX_FORS_TREES, - SPX_WOTS_W); - - printf("Running %d iterations.\n", NTESTS); - - MEASURE("Generating keypair.. ", 1, crypto_sign_keypair(pk, sk)); - MEASURE(" - WOTS pk gen 8x.. ", (1 << SPX_TREE_HEIGHT) / 8, wots_gen_pkx8(wots_pk, &ctx, (uint32_t *) addr)); - MEASURE("Signing.. ", 1, crypto_sign(sm, &smlen, m, SPX_MLEN, sk)); - MEASURE(" - FORS signing.. ", 1, fors_sign(fors_sig, fors_pk, fors_m, &ctx, (uint32_t *) addr)); - MEASURE(" - WOTS pk gen x8.. ", SPX_D * (1 << SPX_TREE_HEIGHT) / 8, wots_gen_pkx8(wots_pk, &ctx, (uint32_t *) addr)); - MEASURE("Verifying.. ", 1, crypto_sign_open(mout, &mlen, sm, smlen, pk)); - - printf("Signature size: %d (%.2f KiB)\n", SPX_BYTES, SPX_BYTES / 1024.0); - printf("Public key size: %d (%.2f KiB)\n", SPX_PK_BYTES, SPX_PK_BYTES / 1024.0); - printf("Secret key size: %d (%.2f KiB)\n", SPX_SK_BYTES, SPX_SK_BYTES / 1024.0); - - free(m); - free(sm); - free(mout); - - return 0; -} - -static void wots_gen_pkx8(unsigned char *pk, const spx_ctx *ctx, - uint32_t addr[8]) { - struct leaf_info_x8 leaf; - unsigned steps[ SPX_WOTS_LEN ] = { 0 }; - INITIALIZE_LEAF_INFO_X8(leaf, addr, steps); - wots_gen_leafx8(pk, ctx, 0, &leaf); -} diff --git a/sphincsplus/sha2-avx2/test/fors.c b/sphincsplus/sha2-avx2/test/fors.c deleted file mode 120000 index b2bccee..0000000 --- a/sphincsplus/sha2-avx2/test/fors.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/fors.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/test/spx.c b/sphincsplus/sha2-avx2/test/spx.c deleted file mode 120000 index 7af26df..0000000 --- a/sphincsplus/sha2-avx2/test/spx.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/spx.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/test/thashx8.c b/sphincsplus/sha2-avx2/test/thashx8.c deleted file mode 100644 index 37d27c3..0000000 --- a/sphincsplus/sha2-avx2/test/thashx8.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include - -#include "../thashx8.h" -#include "../thash.h" -#include "../randombytes.h" -#include "../params.h" -#include "../hash.h" - -#if SPX_SHA512 -#include "../sha2.h" -#include "../sha512x4.h" -#endif - - -int main(void) -{ - /* Make stdout buffer more responsive. */ - setbuf(stdout, NULL); - - unsigned char input[16*SPX_N]; - spx_ctx ctx; - unsigned char output[8*SPX_N]; - unsigned char out8[8*SPX_N]; - uint32_t addr[8*8] = {0}; - unsigned int j; - - randombytes(ctx.pub_seed, SPX_N); - randombytes(input, 16*SPX_N); - randombytes((unsigned char *)addr, 8 * 8 * sizeof(uint32_t)); - - initialize_hash_function(&ctx); - - printf("Testing if thash matches thashx8 on one block ... "); - - for (j = 0; j < 8; j++) { - thash(out8 + j * SPX_N, input + j * SPX_N, 1, &ctx, addr + j*8); - } - - thashx8(output + 0*SPX_N, - output + 1*SPX_N, - output + 2*SPX_N, - output + 3*SPX_N, - output + 4*SPX_N, - output + 5*SPX_N, - output + 6*SPX_N, - output + 7*SPX_N, - input + 0*SPX_N, - input + 1*SPX_N, - input + 2*SPX_N, - input + 3*SPX_N, - input + 4*SPX_N, - input + 5*SPX_N, - input + 6*SPX_N, - input + 7*SPX_N, - 1, &ctx, addr); - - if (memcmp(out8, output, 8 * SPX_N)) { - printf("failed!\n"); - return -1; - } - printf("successful.\n"); - - printf("Testing if thash matches thashx8 on two blocks ... "); - - for (j = 0; j < 8; j++) { - thash(out8 + j * SPX_N, input + (2*j) * SPX_N, 2, &ctx, addr + j*8); - } - - thashx8(output + 0*SPX_N, - output + 1*SPX_N, - output + 2*SPX_N, - output + 3*SPX_N, - output + 4*SPX_N, - output + 5*SPX_N, - output + 6*SPX_N, - output + 7*SPX_N, - input + 0*SPX_N, - input + 2*SPX_N, - input + 4*SPX_N, - input + 6*SPX_N, - input + 8*SPX_N, - input + 10*SPX_N, - input + 12*SPX_N, - input + 14*SPX_N, - 2, &ctx, addr); - - if (memcmp(out8, output, 8 * SPX_N)) { - printf("failed!\n"); - return -1; - } - printf("successful.\n"); - return 0; -} diff --git a/sphincsplus/sha2-avx2/thash.h b/sphincsplus/sha2-avx2/thash.h deleted file mode 120000 index 937dd48..0000000 --- a/sphincsplus/sha2-avx2/thash.h +++ /dev/null @@ -1 +0,0 @@ -../ref/thash.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/thash_sha2_robust.c b/sphincsplus/sha2-avx2/thash_sha2_robust.c deleted file mode 120000 index 60e5139..0000000 --- a/sphincsplus/sha2-avx2/thash_sha2_robust.c +++ /dev/null @@ -1 +0,0 @@ -../ref/thash_sha2_robust.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/thash_sha2_robustx8.c b/sphincsplus/sha2-avx2/thash_sha2_robustx8.c deleted file mode 100644 index 8700d90..0000000 --- a/sphincsplus/sha2-avx2/thash_sha2_robustx8.c +++ /dev/null @@ -1,276 +0,0 @@ -#include -#include - -#include "address.h" -#include "utils.h" -#include "params.h" -#include "thashx8.h" -#include "sha2.h" -#include "sha256x8.h" -#include "sha256avx.h" - -#if SPX_SHA512 -#include "sha512x4.h" - -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8*8] -); -#endif - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8*8]) -{ -#if SPX_SHA512 - if (inblocks > 1) { - thashx8_512( - out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, - inblocks, ctx, addrx8); - return; - } -#endif - SPX_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)); - SPX_VLA(unsigned char, outbufx8, 8 * SPX_SHA256_OUTPUT_BYTES); - SPX_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - addrx8 + i*8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x8(bitmaskx8, inblocks * SPX_N, - bufx8 + 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in0[i] ^ bitmaskx8[i + 0*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in1[i] ^ bitmaskx8[i + 1*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in2[i] ^ bitmaskx8[i + 2*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in3[i] ^ bitmaskx8[i + 3*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in4[i] ^ bitmaskx8[i + 4*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in5[i] ^ bitmaskx8[i + 5*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in6[i] ^ bitmaskx8[i + 6*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in7[i] ^ bitmaskx8[i + 7*(inblocks * SPX_N)]; - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - ctx->state_seeded, 512, - - /* in */ - bufx8 + SPX_N + 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, SPX_N); -} - -#if SPX_SHA512 -/** - * 2x4-way parallel version of thash; this is for the uses of thash that are - * based on SHA-512 - */ -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8*8]) -{ - SPX_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); - SPX_VLA(unsigned char, outbuf, 4 * SPX_SHA512_OUTPUT_BYTES); - SPX_VLA(unsigned char, bitmaskx4, 4 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - addrx8 + i*8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x4_512(bitmaskx4, inblocks * SPX_N, - bufx8 + 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in0[i] ^ bitmaskx4[i + 0*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in1[i] ^ bitmaskx4[i + 1*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in2[i] ^ bitmaskx4[i + 2*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in3[i] ^ bitmaskx4[i + 3*(inblocks * SPX_N)]; - } - - mgf1x4_512(bitmaskx4, inblocks * SPX_N, - bufx8 + 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in4[i] ^ bitmaskx4[i + 0*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in5[i] ^ bitmaskx4[i + 1*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in6[i] ^ bitmaskx4[i + 2*(inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = - in7[i] ^ bitmaskx4[i + 3*(inblocks * SPX_N)]; - } - - sha512x4_seeded( - outbuf + 0*SPX_SHA512_OUTPUT_BYTES, - outbuf + 1*SPX_SHA512_OUTPUT_BYTES, - outbuf + 2*SPX_SHA512_OUTPUT_BYTES, - outbuf + 3*SPX_SHA512_OUTPUT_BYTES, - ctx->state_seeded_512, /* seed */ - 1024, /* seed length */ - bufx8 + SPX_N + 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ - ); - - memcpy(out0, outbuf + 0*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbuf + 1*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbuf + 2*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbuf + 3*SPX_SHA512_OUTPUT_BYTES, SPX_N); - - sha512x4_seeded( - outbuf + 0*SPX_SHA512_OUTPUT_BYTES, - outbuf + 1*SPX_SHA512_OUTPUT_BYTES, - outbuf + 2*SPX_SHA512_OUTPUT_BYTES, - outbuf + 3*SPX_SHA512_OUTPUT_BYTES, - ctx->state_seeded_512, /* seed */ - 1024, /* seed length */ - bufx8 + SPX_N + 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + SPX_N + 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ - ); - - memcpy(out4, outbuf + 0*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbuf + 1*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbuf + 2*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbuf + 3*SPX_SHA512_OUTPUT_BYTES, SPX_N); -} -#endif diff --git a/sphincsplus/sha2-avx2/thash_sha2_simple.c b/sphincsplus/sha2-avx2/thash_sha2_simple.c deleted file mode 120000 index c87305c..0000000 --- a/sphincsplus/sha2-avx2/thash_sha2_simple.c +++ /dev/null @@ -1 +0,0 @@ -../ref/thash_sha2_simple.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/thash_sha2_simplex8.c b/sphincsplus/sha2-avx2/thash_sha2_simplex8.c deleted file mode 100644 index 2b40d02..0000000 --- a/sphincsplus/sha2-avx2/thash_sha2_simplex8.c +++ /dev/null @@ -1,220 +0,0 @@ -#include -#include - -#include "address.h" -#include "utils.h" -#include "params.h" -#include "thashx8.h" -#include "sha2.h" -#include "sha256x8.h" -#include "sha256avx.h" - -#if SPX_SHA512 -#include "sha512x4.h" - -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8*8] -); -#endif - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8*8]) -{ -#if SPX_SHA512 - if (inblocks > 1) { - thashx8_512( - out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, - inblocks, ctx, addrx8); - return; - } -#endif - unsigned char bufx8[8*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)]; - unsigned char outbufx8[8*SPX_SHA256_OUTPUT_BYTES]; - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - addrx8 + i*8, SPX_SHA256_ADDR_BYTES); - } - - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 0*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in0, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 1*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in1, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 2*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in2, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 3*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in3, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 4*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in4, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 5*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in5, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 6*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in6, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 7*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in7, inblocks * SPX_N); - - sha256x8_seeded( - /* out */ - outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - ctx->state_seeded, 512, - - /* in */ - bufx8 + 0*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 1*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 2*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 3*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 4*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 5*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 6*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 7*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, SPX_N); -} - -#if SPX_SHA512 -/** - * 2x4-way parallel version of thash; this is for the uses of thash that are - * based on SHA-512 - */ -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8*8]) -{ - unsigned char bufx8[8*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)]; - unsigned char outbuf[4*SPX_SHA512_OUTPUT_BYTES]; - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - addrx8 + i*8, SPX_SHA256_ADDR_BYTES); - } - - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 0*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in0, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 1*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in1, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 2*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in2, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 3*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in3, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 4*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in4, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 5*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in5, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 6*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in6, inblocks * SPX_N); - memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + - 7*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in7, inblocks * SPX_N); - - sha512x4_seeded( - outbuf + 0*SPX_SHA512_OUTPUT_BYTES, - outbuf + 1*SPX_SHA512_OUTPUT_BYTES, - outbuf + 2*SPX_SHA512_OUTPUT_BYTES, - outbuf + 3*SPX_SHA512_OUTPUT_BYTES, - ctx->state_seeded_512, /* seed */ - 1024, /* seed length */ - bufx8 + 0*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), /* in */ - bufx8 + 1*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 2*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 3*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ - ); - - memcpy(out0, outbuf + 0*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbuf + 1*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbuf + 2*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbuf + 3*SPX_SHA512_OUTPUT_BYTES, SPX_N); - - sha512x4_seeded( - outbuf + 0*SPX_SHA512_OUTPUT_BYTES, - outbuf + 1*SPX_SHA512_OUTPUT_BYTES, - outbuf + 2*SPX_SHA512_OUTPUT_BYTES, - outbuf + 3*SPX_SHA512_OUTPUT_BYTES, - ctx->state_seeded_512, /* seed */ - 1024, /* seed length */ - bufx8 + 4*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), /* in */ - bufx8 + 5*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 6*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - bufx8 + 7*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ - ); - - memcpy(out4, outbuf + 0*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbuf + 1*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbuf + 2*SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbuf + 3*SPX_SHA512_OUTPUT_BYTES, SPX_N); -} -#endif diff --git a/sphincsplus/sha2-avx2/thashx8.h b/sphincsplus/sha2-avx2/thashx8.h deleted file mode 100644 index d6bf618..0000000 --- a/sphincsplus/sha2-avx2/thashx8.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_THASHX8_H -#define SPX_THASHX8_H - -#include -#include "context.h" -#include "params.h" - -#define thashx8 SPX_NAMESPACE(thashx8) -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8*8]); - -#endif diff --git a/sphincsplus/sha2-avx2/utils.c b/sphincsplus/sha2-avx2/utils.c deleted file mode 120000 index e8ef6eb..0000000 --- a/sphincsplus/sha2-avx2/utils.c +++ /dev/null @@ -1 +0,0 @@ -../ref/utils.c \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/utils.h b/sphincsplus/sha2-avx2/utils.h deleted file mode 120000 index 51b0d39..0000000 --- a/sphincsplus/sha2-avx2/utils.h +++ /dev/null @@ -1 +0,0 @@ -../ref/utils.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/utilsx8.c b/sphincsplus/sha2-avx2/utilsx8.c deleted file mode 100644 index af21cf5..0000000 --- a/sphincsplus/sha2-avx2/utilsx8.c +++ /dev/null @@ -1,146 +0,0 @@ -#include - -#include "utils.h" -#include "utilsx8.h" -#include "params.h" -#include "thashx8.h" -#include "address.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx8 to be initialized to 8 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 8 consecutive nodes in the real tree. - * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) - * - * When we get to the top three levels of the real tree (where there is only - * one logical node), we continue this operation three more times; the right - * most real node will by the actual root (and the other 7 nodes will be - * garbage). We follow the same thashx8 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 3; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char* /* Where to write the leaves */, - const spx_ctx*, - uint32_t idx, void *info), - uint32_t tree_addrx8[8*8], - void *info) -{ - /* This is where we keep the intermediate nodes */ - SPX_VLA(unsigned char, stackx8, 8 * tree_height * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1 << (tree_height-3)) - 1; - for (idx = 0;; idx++) { - unsigned char current[8*SPX_N]; /* Current logical node */ - gen_leafx8( current, ctx, 8*idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h=0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 3) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7*SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 8 - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7*SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 3) ^ internal_leaf) & ~0x7) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf&7)^1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 8 nodes into the one root node in three - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - int j; - internal_idx_offset >>= 1; - for (j = 0; j < 8; j++) { - set_tree_height(tree_addrx8 + j*8, h + 1); - set_tree_index(tree_addrx8 + j*8, - (8/2) * (internal_idx&~1) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx8[h * 8 * SPX_N]; - thashx8( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - ¤t[4 * SPX_N], - ¤t[5 * SPX_N], - ¤t[6 * SPX_N], - ¤t[7 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - &left [4 * SPX_N], - &left [6 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - ¤t[4 * SPX_N], - ¤t[6 * SPX_N], - 2, ctx, tree_addrx8); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); - } -} diff --git a/sphincsplus/sha2-avx2/utilsx8.h b/sphincsplus/sha2-avx2/utilsx8.h deleted file mode 100644 index ca42146..0000000 --- a/sphincsplus/sha2-avx2/utilsx8.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_UTILSX8_H -#define SPX_UTILSX8_H - -#include -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 8 at a time (in - * parallel) - */ -#define treehashx8 SPX_NAMESPACE(treehashx8) -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx8)( - unsigned char* /* Where to write the leaves */, - const spx_ctx* /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx8[8*8], void *info); - -#endif diff --git a/sphincsplus/sha2-avx2/wots.c b/sphincsplus/sha2-avx2/wots.c deleted file mode 100644 index 779a868..0000000 --- a/sphincsplus/sha2-avx2/wots.c +++ /dev/null @@ -1,293 +0,0 @@ -#include -#include - -#include "utils.h" -#include "utilsx8.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "wots.h" -#include "wotsx8.h" -#include "address.h" -#include "params.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) -{ - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[8]; - uint32_t addrs[8*8]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, ..., addr} */ - for (j = 0; j < 8; j++) { - memcpy(addrs+j*8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN*SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 8) { - for (j = 0; j < 8 && i+j < SPX_WOTS_LEN; j++) { - idx = idxs[i+j]; - set_chain_addr(addrs+j*8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 7; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i+watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs+j*8, k + start[idxs[i+j]]); - } - - thashx8(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], - bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) -{ - int in = 0; - int out = 0; - unsigned char total; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) -{ - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) -{ - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) -{ - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 8 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x8 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~7) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0; - wots_sign_index = 0; - } - - for (j = 0; j < 8; j++) { - set_keypair_addr( leaf_addr + j*8, leaf_idx + j ); - set_keypair_addr( pk_addr + j*8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ - /* to the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 8; j++) { - set_chain_addr(leaf_addr + j*8, i); - set_hash_addr(leaf_addr + j*8, 0); - set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx8(buffer + 0*wots_offset, - buffer + 1*wots_offset, - buffer + 2*wots_offset, - buffer + 3*wots_offset, - buffer + 4*wots_offset, - buffer + 5*wots_offset, - buffer + 6*wots_offset, - buffer + 7*wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 8; j++) { - set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k=0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index*wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) break; - - /* Iterate one step on all 8 chains */ - for (j = 0; j < 8; j++) { - set_hash_addr(leaf_addr + j*8, k); - } - thashx8(buffer + 0*wots_offset, - buffer + 1*wots_offset, - buffer + 2*wots_offset, - buffer + 3*wots_offset, - buffer + 4*wots_offset, - buffer + 5*wots_offset, - buffer + 6*wots_offset, - buffer + 7*wots_offset, - buffer + 0*wots_offset, - buffer + 1*wots_offset, - buffer + 2*wots_offset, - buffer + 3*wots_offset, - buffer + 4*wots_offset, - buffer + 5*wots_offset, - buffer + 6*wots_offset, - buffer + 7*wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx8(dest + 0*SPX_N, - dest + 1*SPX_N, - dest + 2*SPX_N, - dest + 3*SPX_N, - dest + 4*SPX_N, - dest + 5*SPX_N, - dest + 6*SPX_N, - dest + 7*SPX_N, - pk_buffer + 0*wots_offset, - pk_buffer + 1*wots_offset, - pk_buffer + 2*wots_offset, - pk_buffer + 3*wots_offset, - pk_buffer + 4*wots_offset, - pk_buffer + 5*wots_offset, - pk_buffer + 6*wots_offset, - pk_buffer + 7*wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/sphincsplus/sha2-avx2/wots.h b/sphincsplus/sha2-avx2/wots.h deleted file mode 120000 index 8c327ea..0000000 --- a/sphincsplus/sha2-avx2/wots.h +++ /dev/null @@ -1 +0,0 @@ -../ref/wots.h \ No newline at end of file diff --git a/sphincsplus/sha2-avx2/wotsx8.h b/sphincsplus/sha2-avx2/wotsx8.h deleted file mode 100644 index 10f72ad..0000000 --- a/sphincsplus/sha2-avx2/wotsx8.h +++ /dev/null @@ -1,40 +0,0 @@ -#if !defined( WOTSX8_H_ ) -#define WOTSX8_H_ - -#include -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx8 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x8 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8*8]; - uint32_t pk_addr[8*8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ - info.wots_sig = 0; \ - info.wots_sign_leaf = ~0; \ - info.wots_steps = step_buffer; \ - int i; \ - for (i=0; i<8; i++) { \ - memcpy( &info.leaf_addr[8*i], addr, 32 ); \ - memcpy( &info.pk_addr[8*i], addr, 32 ); \ - } \ -} - -#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX8_H_ */ diff --git a/sphincsplus/shake-a64/.gitignore b/sphincsplus/shake-a64/.gitignore deleted file mode 100644 index 67bcef9..0000000 --- a/sphincsplus/shake-a64/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -test/* -!test/*.c -PQCsignKAT_*.rsp -PQCsignKAT_*.req -PQCgenKAT_sign diff --git a/sphincsplus/shake-a64/Makefile b/sphincsplus/shake-a64/Makefile deleted file mode 100644 index d3b566a..0000000 --- a/sphincsplus/shake-a64/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -PARAMS = sphincs-shake-128f -THASH = robust - -CFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3 -std=c99 -fomit-frame-pointer -flto -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) - -SOURCES = hash_shake.c hash_shakex2.c thash_shake_$(THASH)x2.c address.c randombytes.c merkle.c wots.c utils.c utilsx2.c fors.c sign.c fips202.c fips202x2.c f1600x2_const.c f1600x2.s -HEADERS = params.h hash.h hashx2.h thashx2.h address.h randombytes.h merkle.h wots.h utils.h utilsx2.h fors.h api.h fips202.h fips202x2.h f1600x2.h thash.h - -DET_SOURCES = $(SOURCES:randombytes.%=rng.%) -DET_HEADERS = $(HEADERS:randombytes.%=rng.%) - -TESTS = test/fors \ - test/spx \ - test/thashx2 \ - -BENCHMARK = test/benchmark - -.PHONY: clean test benchmark - -default: PQCgenKAT_sign - -all: PQCgenKAT_sign tests benchmarks - -tests: $(TESTS) - -test: $(TESTS:=.exec) - -benchmarks: $(BENCHMARK) - -benchmark: $(BENCHMARK:=.exec) - -PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) - $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto - -test/benchmark: test/benchmark.c test/cycles.c $(SOURCES) $(HEADERS) - $(CC) $(CFLAGS) -o $@ test/cycles.c $(SOURCES) $< $(LDLIBS) - -test/%: test/%.c $(SOURCES) $(HEADERS) - $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) - -test/%.exec: test/% - @$< - -clean: - -$(RM) $(TESTS) - -$(RM) $(BENCHMARK) - -$(RM) PQCgenKAT_sign - -$(RM) PQCsignKAT_*.rsp - -$(RM) PQCsignKAT_*.req diff --git a/sphincsplus/shake-a64/PQCgenKAT_sign.c b/sphincsplus/shake-a64/PQCgenKAT_sign.c deleted file mode 120000 index a17dbe2..0000000 --- a/sphincsplus/shake-a64/PQCgenKAT_sign.c +++ /dev/null @@ -1 +0,0 @@ -../ref/PQCgenKAT_sign.c \ No newline at end of file diff --git a/sphincsplus/shake-a64/address.c b/sphincsplus/shake-a64/address.c deleted file mode 120000 index 02c52c6..0000000 --- a/sphincsplus/shake-a64/address.c +++ /dev/null @@ -1 +0,0 @@ -../ref/address.c \ No newline at end of file diff --git a/sphincsplus/shake-a64/address.h b/sphincsplus/shake-a64/address.h deleted file mode 120000 index e670da5..0000000 --- a/sphincsplus/shake-a64/address.h +++ /dev/null @@ -1 +0,0 @@ -../ref/address.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/api.h b/sphincsplus/shake-a64/api.h deleted file mode 120000 index ea89e0a..0000000 --- a/sphincsplus/shake-a64/api.h +++ /dev/null @@ -1 +0,0 @@ -../ref/api.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/context.h b/sphincsplus/shake-a64/context.h deleted file mode 100644 index 993c9ce..0000000 --- a/sphincsplus/shake-a64/context.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#endif diff --git a/sphincsplus/shake-a64/f1600x2.h b/sphincsplus/shake-a64/f1600x2.h deleted file mode 100644 index 70c5a8e..0000000 --- a/sphincsplus/shake-a64/f1600x2.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SPX_F1600X2_H -#define SPX_F1600X2_H - -#include - -extern uint64_t f1600_RC[24]; -extern void _f1600x2(uint64_t* a, uint64_t* rc); - -#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) - -#endif diff --git a/sphincsplus/shake-a64/f1600x2.s b/sphincsplus/shake-a64/f1600x2.s deleted file mode 100644 index 640ed79..0000000 --- a/sphincsplus/shake-a64/f1600x2.s +++ /dev/null @@ -1,143 +0,0 @@ -# From https://github.com/bwesterb/armed-keccak - -.macro round - # Execute theta, but without xoring into the state yet. - # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. - eor3.16b v25, v0, v5, v10 - eor3.16b v26, v1, v6, v11 - eor3.16b v27, v2, v7, v12 - eor3.16b v28, v3, v8, v13 - eor3.16b v29, v4, v9, v14 - - eor3.16b v25, v25, v15, v20 - eor3.16b v26, v26, v16, v21 - eor3.16b v27, v27, v17, v22 - eor3.16b v28, v28, v18, v23 - eor3.16b v29, v29, v19, v24 - - # d[0] = rotl(p[1], 1) ^ p[4] - rax1.2d v30, v29, v26 - # d[3] = rotl(p[4], 1) ^ p[2] - rax1.2d v29, v27, v29 - # d[1] = rotl(p[2], 1) ^ p[0] - rax1.2d v27, v25, v27 - # d[4] = rotl(p[0], 1) ^ p[3] - rax1.2d v25, v28, v25 - # d[2] = rotl(p[3], 1) ^ p[1] - rax1.2d v28, v26, v28 - - # Xor parities from step theta into the state at the same time - # as executing rho and pi. - eor.16b v0, v0, v30 - mov.16b v31, v1 - xar.2d v1, v6, v27, 20 - xar.2d v6, v9, v25, 44 - xar.2d v9, v22, v28, 3 - xar.2d v22, v14, v25, 25 - xar.2d v14, v20, v30, 46 - xar.2d v20, v2, v28, 2 - xar.2d v2, v12, v28, 21 - xar.2d v12, v13, v29, 39 - xar.2d v13, v19, v25, 56 - xar.2d v19, v23, v29, 8 - xar.2d v23, v15, v30, 23 - xar.2d v15, v4, v25, 37 - xar.2d v4, v24, v25, 50 - xar.2d v24, v21, v27, 62 - xar.2d v21, v8, v29, 9 - xar.2d v8, v16, v27, 19 - xar.2d v16, v5, v30, 28 - xar.2d v5, v3, v29, 36 - xar.2d v3, v18, v29, 43 - xar.2d v18, v17, v28, 49 - xar.2d v17, v11, v27, 54 - xar.2d v11, v7, v28, 58 - xar.2d v7, v10, v30, 61 - xar.2d v10, v31, v27, 63 - - # Chi - bcax.16b v25, v0, v2, v1 - bcax.16b v26, v1, v3, v2 - bcax.16b v2, v2, v4, v3 - bcax.16b v3, v3, v0, v4 - bcax.16b v4, v4, v1, v0 - mov.16b v0, v25 - mov.16b v1, v26 - - bcax.16b v25, v5, v7, v6 - bcax.16b v26, v6, v8, v7 - bcax.16b v7, v7, v9, v8 - bcax.16b v8, v8, v5, v9 - bcax.16b v9, v9, v6, v5 - mov.16b v5, v25 - mov.16b v6, v26 - - bcax.16b v25, v10, v12, v11 - bcax.16b v26, v11, v13, v12 - bcax.16b v12, v12, v14, v13 - bcax.16b v13, v13, v10, v14 - bcax.16b v14, v14, v11, v10 - mov.16b v10, v25 - mov.16b v11, v26 - - bcax.16b v25, v15, v17, v16 - bcax.16b v26, v16, v18, v17 - bcax.16b v17, v17, v19, v18 - bcax.16b v18, v18, v15, v19 - bcax.16b v19, v19, v16, v15 - mov.16b v15, v25 - mov.16b v16, v26 - - bcax.16b v25, v20, v22, v21 - bcax.16b v26, v21, v23, v22 - bcax.16b v22, v22, v24, v23 - bcax.16b v23, v23, v20, v24 - bcax.16b v24, v24, v21, v20 - mov.16b v20, v25 - mov.16b v21, v26 - - # iota - ld1r {v25.2d}, [x1], #8 - eor.16b v0, v0, v25 -.endm - -.align 4 -.global __f1600x2 -__f1600x2: - stp d8, d9, [sp,#-16]! - stp d10, d11, [sp,#-16]! - stp d12, d13, [sp,#-16]! - stp d14, d15, [sp,#-16]! - - mov x2, x0 - mov x3, #24 - - ld1.2d {v0, v1, v2, v3}, [x0], #64 - ld1.2d {v4, v5, v6, v7}, [x0], #64 - ld1.2d {v8, v9, v10, v11}, [x0], #64 - ld1.2d {v12, v13, v14, v15}, [x0], #64 - ld1.2d {v16, v17, v18, v19}, [x0], #64 - ld1.2d {v20, v21, v22, v23}, [x0], #64 - ld1.2d {v24}, [x0] - -loop: - round - - subs x3, x3, #1 - cbnz x3, loop - - mov x0, x2 - st1.2d {v0, v1, v2, v3}, [x0], #64 - st1.2d {v4, v5, v6, v7}, [x0], #64 - st1.2d {v8, v9, v10, v11}, [x0], #64 - st1.2d {v12, v13, v14, v15}, [x0], #64 - st1.2d {v16, v17, v18, v19}, [x0], #64 - st1.2d {v20, v21, v22, v23}, [x0], #64 - st1.2d {v24}, [x0] - - ldp d14, d15, [sp], #16 - ldp d12, d13, [sp], #16 - ldp d10, d11, [sp], #16 - ldp d8, d9, [sp], #16 - - ret lr diff --git a/sphincsplus/shake-a64/f1600x2_const.c b/sphincsplus/shake-a64/f1600x2_const.c deleted file mode 100644 index 6880176..0000000 --- a/sphincsplus/shake-a64/f1600x2_const.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "f1600x2.h" - -uint64_t f1600_RC[24] = { - 0x0000000000000001, - 0x0000000000008082, - 0x800000000000808A, - 0x8000000080008000, - 0x000000000000808B, - 0x0000000080000001, - 0x8000000080008081, - 0x8000000000008009, - 0x000000000000008A, - 0x0000000000000088, - 0x0000000080008009, - 0x000000008000000A, - 0x000000008000808B, - 0x800000000000008B, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x000000000000800A, - 0x800000008000000A, - 0x8000000080008081, - 0x8000000000008080, - 0x0000000080000001, - 0x8000000080008008, -}; - - diff --git a/sphincsplus/shake-a64/fips202.c b/sphincsplus/shake-a64/fips202.c deleted file mode 120000 index da2fa42..0000000 --- a/sphincsplus/shake-a64/fips202.c +++ /dev/null @@ -1 +0,0 @@ -../ref/fips202.c \ No newline at end of file diff --git a/sphincsplus/shake-a64/fips202.h b/sphincsplus/shake-a64/fips202.h deleted file mode 120000 index c759415..0000000 --- a/sphincsplus/shake-a64/fips202.h +++ /dev/null @@ -1 +0,0 @@ -../ref/fips202.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/fips202x2.c b/sphincsplus/shake-a64/fips202x2.c deleted file mode 100644 index 87c0df8..0000000 --- a/sphincsplus/shake-a64/fips202x2.c +++ /dev/null @@ -1,165 +0,0 @@ -#include -#include - -#include "fips202x2.h" -#include "fips202.h" -#include "f1600x2.h" - -uint64_t load64(const unsigned char *x) -{ - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -void store64(uint8_t *x, uint64_t u) -{ - unsigned int i; - - for(i=0; i<8; ++i) { - x[i] = u; - u >>= 8; - } -} - -static void keccak_absorb2x(uint64_t *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - unsigned long long int mlen, - unsigned char p) -{ - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - - while (mlen >= r) - { - for (i = 0; i < r / 8; ++i) - { - s[2*i+0] ^= load64(m0 + 8 * i); - s[2*i+1] ^= load64(m1 + 8 * i); - } - - f1600x2(s); - mlen -= r; - m0 += r; - m1 += r; - } - - for (i = 0; i < r; ++i) - { - t0[i] = 0; - t1[i] = 0; - } - for (i = 0; i < mlen; ++i) - { - t0[i] = m0[i]; - t1[i] = m1[i]; - } - - t0[i] = p; - t1[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) - { - s[2*i+0] ^= load64(t0 + 8 * i); - s[2*i+1] ^= load64(t1 + 8 * i); - } -} - - -static void keccak_squeezeblocks2x(unsigned char *h0, - unsigned char *h1, - unsigned long long int nblocks, - uint64_t *s, - unsigned int r) -{ - unsigned int i; - - while(nblocks > 0) - { - f1600x2(s); - for(i=0;i<(r>>3);i++) - { - store64(h0+8*i, s[2*i+0]); - store64(h1+8*i, s[2*i+1]); - } - h0 += r; - h1 += r; - nblocks--; - } -} - - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) -{ - uint64_t s[50] = {0}; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned int i; - - /* absorb 4 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen/SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; - out1 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; - - if(outlen%SHAKE128_RATE) - { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); - for(i=0;i - -uint64_t load64(const unsigned char *x); -void store64(uint8_t *x, uint64_t u); - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -#endif diff --git a/sphincsplus/shake-a64/fors.c b/sphincsplus/shake-a64/fors.c deleted file mode 100644 index a19fc7e..0000000 --- a/sphincsplus/shake-a64/fors.c +++ /dev/null @@ -1,198 +0,0 @@ -#include -#include -#include - -#include "thash.h" -#include "fors.h" -#include "utils.h" -#include "utilsx2.h" -#include "hash.h" -#include "hashx2.h" -#include "thashx2.h" -#include "address.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) -{ - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx2(unsigned char *sk0, - unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2*8]) -{ - prf_addrx2(sk0, sk1, - ctx, fors_leaf_addrx2); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) -{ - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx2(unsigned char *leaf0, - unsigned char *leaf1, - const unsigned char *sk0, - const unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2*8]) -{ - thashx2(leaf0, leaf1, - sk0, sk1, - 1, ctx, fors_leaf_addrx2); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[2*8]; -}; - -static void fors_gen_leafx2(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) -{ - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 2; j++) { - set_tree_index(fors_leaf_addrx2 + j*8, addr_idx + j); - set_type(fors_leaf_addrx2 + j*8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx2(leaf + 0*SPX_N, - leaf + 1*SPX_N, - ctx, fors_leaf_addrx2); - - for (j = 0; j < 2; j++) { - set_type(fors_leaf_addrx2 + j*8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx2(leaf + 0*SPX_N, - leaf + 1*SPX_N, - leaf + 0*SPX_N, - leaf + 1*SPX_N, - ctx, fors_leaf_addrx2); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) -{ - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= ((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) -{ - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[2*8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i=0; i<2; i++) { - copy_keypair_addr(fors_tree_addr + 8*i, fors_addr); - set_type(fors_tree_addr + 8*i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8*i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx2(roots + i*SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) -{ - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i*SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/sphincsplus/shake-a64/fors.h b/sphincsplus/shake-a64/fors.h deleted file mode 120000 index 07156bd..0000000 --- a/sphincsplus/shake-a64/fors.h +++ /dev/null @@ -1 +0,0 @@ -../ref/fors.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/hash.h b/sphincsplus/shake-a64/hash.h deleted file mode 120000 index cffc52b..0000000 --- a/sphincsplus/shake-a64/hash.h +++ /dev/null @@ -1 +0,0 @@ -../ref/hash.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/hash_shake.c b/sphincsplus/shake-a64/hash_shake.c deleted file mode 120000 index 1d9d0cd..0000000 --- a/sphincsplus/shake-a64/hash_shake.c +++ /dev/null @@ -1 +0,0 @@ -../ref/hash_shake.c \ No newline at end of file diff --git a/sphincsplus/shake-a64/hash_shakex2.c b/sphincsplus/shake-a64/hash_shakex2.c deleted file mode 100644 index d6f36c2..0000000 --- a/sphincsplus/shake-a64/hash_shakex2.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "fips202x2.h" -#include "f1600x2.h" -#include "hashx2.h" - -/* - * 2-way parallel version of prf_addr; takes 2x as much input and output - */ -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2*8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - - for (int i = 0; i < SPX_N/8; i++) { - uint64_t x = load64(ctx->pub_seed + 8*i); - state[2*i] = x; - state[2*i+1] = x; - } - for (int i = 0; i < 4; i++) { - state[2*(SPX_N/8 + i)] = (((uint64_t)addrx2[1+2*i]) << 32) - | (uint64_t)addrx2[2*i]; - state[2*(SPX_N/8 + i) + 1] = (((uint64_t)addrx2[8+1+2*i]) << 32) - | (uint64_t)addrx2[8+2*i]; - } - for (int i = 0; i < SPX_N/8; i++) { - uint64_t x = load64(ctx->sk_seed + 8*i); - state[2*(SPX_N/8+i+4)] = x; - state[2*(SPX_N/8+i+4)+1] = x; - } - - /* SHAKE domain separator and padding. */ - state[2*(SPX_N/4+4)] = 0x1f; - state[2*(SPX_N/4+4)+1] = 0x1f; - - state[2*16] = 0x80ULL << 56; - state[2*16+1] = 0x80ULL << 56; - - f1600x2(state); - - for (int i = 0; i < SPX_N/8; i++) { - store64(out0 + 8*i, state[2*i]); - store64(out1 + 8*i, state[2*i+1]); - } -} diff --git a/sphincsplus/shake-a64/hashx2.h b/sphincsplus/shake-a64/hashx2.h deleted file mode 100644 index 25ce94d..0000000 --- a/sphincsplus/shake-a64/hashx2.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SPX_HASHX2_H -#define SPX_HASHX2_H - -#include -#include "context.h" -#include "params.h" - -#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2*8]); - -#endif diff --git a/sphincsplus/shake-a64/merkle.c b/sphincsplus/shake-a64/merkle.c deleted file mode 100644 index b2791d1..0000000 --- a/sphincsplus/shake-a64/merkle.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -#include "utils.h" -#include "utilsx2.h" -#include "wots.h" -#include "wotsx2.h" -#include "merkle.h" -#include "address.h" -#include "params.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx* ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) -{ - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx2[2*8] = { 0 }; - int j; - struct leaf_info_x2 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j=0; j<2; j++) { - set_type(&tree_addrx2[8*j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8*j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8*j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx2[8*j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8*j], wots_addr); - copy_subtree_addr(&info.pk_addr[8*j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx2(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx2, - tree_addrx2, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) -{ - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/sphincsplus/shake-a64/merkle.h b/sphincsplus/shake-a64/merkle.h deleted file mode 120000 index 7d167ed..0000000 --- a/sphincsplus/shake-a64/merkle.h +++ /dev/null @@ -1 +0,0 @@ -../ref/merkle.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/params.h b/sphincsplus/shake-a64/params.h deleted file mode 120000 index 53133cc..0000000 --- a/sphincsplus/shake-a64/params.h +++ /dev/null @@ -1 +0,0 @@ -../ref/params.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/params/params-sphincs-shake-128f.h b/sphincsplus/shake-a64/params/params-sphincs-shake-128f.h deleted file mode 120000 index c65db98..0000000 --- a/sphincsplus/shake-a64/params/params-sphincs-shake-128f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-128f.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/params/params-sphincs-shake-128s.h b/sphincsplus/shake-a64/params/params-sphincs-shake-128s.h deleted file mode 120000 index 18671f7..0000000 --- a/sphincsplus/shake-a64/params/params-sphincs-shake-128s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-128s.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/params/params-sphincs-shake-192f.h b/sphincsplus/shake-a64/params/params-sphincs-shake-192f.h deleted file mode 120000 index d071e35..0000000 --- a/sphincsplus/shake-a64/params/params-sphincs-shake-192f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-192f.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/params/params-sphincs-shake-192s.h b/sphincsplus/shake-a64/params/params-sphincs-shake-192s.h deleted file mode 120000 index 267e2c8..0000000 --- a/sphincsplus/shake-a64/params/params-sphincs-shake-192s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-192s.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/params/params-sphincs-shake-256f.h b/sphincsplus/shake-a64/params/params-sphincs-shake-256f.h deleted file mode 120000 index 3b4743b..0000000 --- a/sphincsplus/shake-a64/params/params-sphincs-shake-256f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-256f.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/params/params-sphincs-shake-256s.h b/sphincsplus/shake-a64/params/params-sphincs-shake-256s.h deleted file mode 120000 index 0795ee1..0000000 --- a/sphincsplus/shake-a64/params/params-sphincs-shake-256s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-256s.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/randombytes.c b/sphincsplus/shake-a64/randombytes.c deleted file mode 120000 index 59a42a5..0000000 --- a/sphincsplus/shake-a64/randombytes.c +++ /dev/null @@ -1 +0,0 @@ -../ref/randombytes.c \ No newline at end of file diff --git a/sphincsplus/shake-a64/randombytes.h b/sphincsplus/shake-a64/randombytes.h deleted file mode 120000 index 055e443..0000000 --- a/sphincsplus/shake-a64/randombytes.h +++ /dev/null @@ -1 +0,0 @@ -../ref/randombytes.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/rng.c b/sphincsplus/shake-a64/rng.c deleted file mode 120000 index 6e2fdac..0000000 --- a/sphincsplus/shake-a64/rng.c +++ /dev/null @@ -1 +0,0 @@ -../ref/rng.c \ No newline at end of file diff --git a/sphincsplus/shake-a64/rng.h b/sphincsplus/shake-a64/rng.h deleted file mode 120000 index d678c7c..0000000 --- a/sphincsplus/shake-a64/rng.h +++ /dev/null @@ -1 +0,0 @@ -../ref/rng.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/shake_offsets.h b/sphincsplus/shake-a64/shake_offsets.h deleted file mode 120000 index 8cfe4c0..0000000 --- a/sphincsplus/shake-a64/shake_offsets.h +++ /dev/null @@ -1 +0,0 @@ -../ref/shake_offsets.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/sign.c b/sphincsplus/shake-a64/sign.c deleted file mode 120000 index 42fea88..0000000 --- a/sphincsplus/shake-a64/sign.c +++ /dev/null @@ -1 +0,0 @@ -../ref/sign.c \ No newline at end of file diff --git a/sphincsplus/shake-a64/test/benchmark.c b/sphincsplus/shake-a64/test/benchmark.c deleted file mode 100644 index a1affb0..0000000 --- a/sphincsplus/shake-a64/test/benchmark.c +++ /dev/null @@ -1,175 +0,0 @@ -#define _POSIX_C_SOURCE 199309L - -#include -#include -#include - -#include "../thash.h" -#include "../thashx2.h" -#include "../api.h" -#include "../f1600x2.h" -#include "../fors.h" -#include "../wots.h" -#include "../wotsx2.h" -#include "../params.h" -#include "../randombytes.h" - -#include "cycles.h" - -#define SPX_MLEN 32 -#define NTESTS 10 - -static void wots_gen_pkx2(unsigned char *pk, const spx_ctx *ctx, - uint32_t addr[8]); - -static int cmp_llu(const void *a, const void*b) -{ - if(*(unsigned long long *)a < *(unsigned long long *)b) return -1; - if(*(unsigned long long *)a > *(unsigned long long *)b) return 1; - return 0; -} - -static unsigned long long median(unsigned long long *l, size_t llen) -{ - qsort(l,llen,sizeof(unsigned long long),cmp_llu); - - if(llen%2) return l[llen/2]; - else return (l[llen/2-1]+l[llen/2])/2; -} - -static void delta(unsigned long long *l, size_t llen) -{ - unsigned int i; - for(i = 0; i < llen - 1; i++) { - l[i] = l[i+1] - l[i]; - } -} - -static void printfcomma (unsigned long long n) -{ - if (n < 1000) { - printf("%llu", n); - return; - } - printfcomma(n / 1000); - printf (",%03llu", n % 1000); -} - -static void printfalignedcomma (unsigned long long n, int len) -{ - unsigned long long ncopy = n; - int i = 0; - - while (ncopy > 9) { - len -= 1; - ncopy /= 10; - i += 1; // to account for commas - } - i = i/3 - 1; // to account for commas - for (; i < len; i++) { - printf(" "); - } - printfcomma(n); -} - -static void display_result(double result, unsigned long long *l, size_t llen, unsigned long long mul) -{ - unsigned long long med; - - result /= NTESTS; - delta(l, NTESTS + 1); - med = median(l, llen); - printf("avg. %11.2lf us (%2.2lf sec); median ", result, result / 1e6); - printfalignedcomma(med, 12); - printf(" cycles, %5llux: ", mul); - printfalignedcomma(mul*med, 12); - printf(" cycles\n"); -} - -#define MEASURE_GENERIC(TEXT, MUL, FNCALL, CORR)\ - printf(TEXT);\ - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);\ - for(i = 0; i < NTESTS; i++) {\ - t[i] = cpucycles() / CORR;\ - FNCALL;\ - }\ - t[NTESTS] = cpucycles();\ - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop);\ - result = ((stop.tv_sec - start.tv_sec) * 1e6 + \ - (stop.tv_nsec - start.tv_nsec) / 1e3) / (double)CORR;\ - display_result(result, t, NTESTS, MUL); -#define MEASURT(TEXT, MUL, FNCALL)\ - MEASURE_GENERIC(\ - TEXT, MUL,\ - do {\ - for (int j = 0; j < 1000; j++) {\ - FNCALL;\ - }\ - } while (0);,\ - 1000); -#define MEASURE(TEXT, MUL, FNCALL) MEASURE_GENERIC(TEXT, MUL, FNCALL, 1) - -int main(void) -{ - init_cpucycles(); - /* Make stdout buffer more responsive. */ - setbuf(stdout, NULL); - - spx_ctx ctx; - unsigned char pk[SPX_PK_BYTES]; - unsigned char sk[SPX_SK_BYTES]; - unsigned char *m = malloc(SPX_MLEN); - unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); - unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); - - unsigned char fors_pk[SPX_FORS_PK_BYTES]; - unsigned char fors_m[SPX_FORS_MSG_BYTES]; - unsigned char fors_sig[SPX_FORS_BYTES]; - unsigned char addr[SPX_ADDR_BYTES*2]; - unsigned char wots_pk[4*SPX_WOTS_PK_BYTES]; - unsigned char block[SPX_N]; - - unsigned long long smlen; - unsigned long long mlen; - unsigned long long t[NTESTS+1]; - struct timespec start, stop; - double result; - int i; - uint64_t statex2[50]; - - randombytes(m, SPX_MLEN); - randombytes(addr, SPX_ADDR_BYTES*2); - - printf("Parameters: n = %d, h = %d, d = %d, b = %d, k = %d, w = %d\n", - SPX_N, SPX_FULL_HEIGHT, SPX_D, SPX_FORS_HEIGHT, SPX_FORS_TREES, - SPX_WOTS_W); - - printf("Running %d iterations.\n", NTESTS); - - MEASURT("thash ", 1, thash(block, block, 1, &ctx, (uint32_t*)addr)); - MEASURT("f1600x2 ", 1, f1600x2(statex2)); - MEASURT("thashx2 ", 1, thashx2(block, block, block, block, 1, &ctx, (uint32_t*)addr)); - MEASURE("Generating keypair.. ", 1, crypto_sign_keypair(pk, sk)); - MEASURE(" - WOTS pk gen 2x.. ", (1 << SPX_TREE_HEIGHT) / 2, wots_gen_pkx2(wots_pk, &ctx, (uint32_t *) addr)); - MEASURE("Signing.. ", 1, crypto_sign(sm, &smlen, m, SPX_MLEN, sk)); - MEASURE(" - FORS signing.. ", 1, fors_sign(fors_sig, fors_pk, fors_m, &ctx, (uint32_t *) addr)); - MEASURE(" - WOTS pk gen x2.. ", SPX_D * (1 << SPX_TREE_HEIGHT) / 2, wots_gen_pkx2(wots_pk, &ctx, (uint32_t *) addr)); - MEASURE("Verifying.. ", 1, crypto_sign_open(mout, &mlen, sm, smlen, pk)); - - printf("Signature size: %d (%.2f KiB)\n", SPX_BYTES, SPX_BYTES / 1024.0); - printf("Public key size: %d (%.2f KiB)\n", SPX_PK_BYTES, SPX_PK_BYTES / 1024.0); - printf("Secret key size: %d (%.2f KiB)\n", SPX_SK_BYTES, SPX_SK_BYTES / 1024.0); - - free(m); - free(sm); - free(mout); - - return 0; -} - -static void wots_gen_pkx2(unsigned char *pk, const spx_ctx *ctx, uint32_t addr[8]) { - struct leaf_info_x2 leaf; - unsigned steps[ SPX_WOTS_LEN ] = { 0 }; - INITIALIZE_LEAF_INFO_X2(leaf, addr, steps); - wots_gen_leafx2(pk, ctx, 0, &leaf); -} diff --git a/sphincsplus/shake-a64/test/cycles.c b/sphincsplus/shake-a64/test/cycles.c deleted file mode 120000 index 513f008..0000000 --- a/sphincsplus/shake-a64/test/cycles.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/cycles.c \ No newline at end of file diff --git a/sphincsplus/shake-a64/test/fors.c b/sphincsplus/shake-a64/test/fors.c deleted file mode 120000 index b2bccee..0000000 --- a/sphincsplus/shake-a64/test/fors.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/fors.c \ No newline at end of file diff --git a/sphincsplus/shake-a64/test/spx.c b/sphincsplus/shake-a64/test/spx.c deleted file mode 120000 index 7af26df..0000000 --- a/sphincsplus/shake-a64/test/spx.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/spx.c \ No newline at end of file diff --git a/sphincsplus/shake-a64/test/thashx2.c b/sphincsplus/shake-a64/test/thashx2.c deleted file mode 100644 index 0b55b13..0000000 --- a/sphincsplus/shake-a64/test/thashx2.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include - -#include "../thashx2.h" -#include "../thash.h" -#include "../randombytes.h" -#include "../params.h" - -int main(void) -{ - /* Make stdout buffer more responsive. */ - setbuf(stdout, NULL); - - unsigned char input[2*SPX_N]; - unsigned char output[2*SPX_N]; - unsigned char out2[2*SPX_N]; - uint32_t addr[2*8] = {0}; - unsigned int j; - spx_ctx ctx; - - randombytes(ctx.pub_seed, SPX_N); - randombytes(input, 4*SPX_N); - randombytes((unsigned char *)addr, 2 * 8 * sizeof(uint32_t)); - - printf("Testing if thash matches thashx2.. "); - - for (j = 0; j < 2; j++) { - thash(out2 + j * SPX_N, input + j * SPX_N, 1, &ctx, addr + j*8); - } - - thashx2(output + 0*SPX_N, - output + 1*SPX_N, - input + 0*SPX_N, - input + 1*SPX_N, - 1, &ctx, addr); - - if (memcmp(out2, output, 2 * SPX_N)) { - printf("failed!\n"); - return -1; - } - printf("successful.\n"); - return 0; -} diff --git a/sphincsplus/shake-a64/thash.h b/sphincsplus/shake-a64/thash.h deleted file mode 100644 index ec9222c..0000000 --- a/sphincsplus/shake-a64/thash.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef SPX_THASHX2_AS_ONE -#define SPX_THASHX2_AS_ONE - -#include -#include "context.h" - -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - - -#endif - diff --git a/sphincsplus/shake-a64/thash_shake_robustx2.c b/sphincsplus/shake-a64/thash_shake_robustx2.c deleted file mode 100644 index 77e09ff..0000000 --- a/sphincsplus/shake-a64/thash_shake_robustx2.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include - -#include "thash.h" -#include "thashx2.h" -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "f1600x2.h" -#include "fips202x2.h" - - -void thash(unsigned char *out, - const unsigned char *in, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t addrx2 [2*8] = { - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] - }; - thashx2(out, out, in, in, inblocks, ctx, addrx2); -} - -/** - * 2-way parallel version of thash; takes 2x as much input and output - */ -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2*8]) -{ - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the twoway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - uint64_t state2[50]; - - for (int i = 0; i < SPX_N/8; i++) { - uint64_t x = load64(ctx->pub_seed + 8*i); - state[2*i] = x; - state[2*i+1] = x; - } - for (int i = 0; i < 4; i++) { - state[2*(SPX_N/8 + i)] = (((uint64_t)addrx2[1+2*i]) << 32) - | (uint64_t)addrx2[2*i]; - state[2*(SPX_N/8 + i) + 1] = (((uint64_t)addrx2[8+1+2*i]) << 32) - | (uint64_t)addrx2[8+2*i]; - } - - /* Domain separator and padding. */ - state[2*16] = 0x80ULL << 56; - state[2*16+1] = 0x80ULL << 56; - - state[2*((SPX_N/8)+4)] ^= 0x1f; - state[2*((SPX_N/8)+4)+1] ^= 0x1f; - - /* We will permutate state2 with f1600x2 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is almost identical. */ - memcpy(state2, state, 400); - - f1600x2(state); - - /* By copying from state, state2 already contains the pub_seed - * and address. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N/8) * inblocks; i++) { - state2[2*(SPX_N/8+4+i)] = state[2*i] ^ load64(in0 + 8*i); - state2[2*(SPX_N/8+4+i)+1] = state[2*i+1] ^ load64(in1 + 8*i); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[2*((SPX_N/8)*(1+inblocks)+4)] ^= 0x1f; - state2[2*((SPX_N/8)*(1+inblocks)+4)+1] ^= 0x1f; - - f1600x2(state2); - - for (int i = 0; i < SPX_N/8; i++) { - store64(out0 + 8*i, state2[2*i]); - store64(out1 + 8*i, state2[2*i+1]); - } - } else { - SPX_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - SPX_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - SPX_VLA(unsigned char, bitmask0, inblocks * SPX_N); - SPX_VLA(unsigned char, bitmask1, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx2 + 0*8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx2 + 1*8, SPX_ADDR_BYTES); - - shake256x2(bitmask0, bitmask1, inblocks * SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - } - - shake256x2(out0, out1, SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - } -} diff --git a/sphincsplus/shake-a64/thash_shake_simplex2.c b/sphincsplus/shake-a64/thash_shake_simplex2.c deleted file mode 100644 index 0bd7130..0000000 --- a/sphincsplus/shake-a64/thash_shake_simplex2.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "thash.h" -#include "thashx2.h" -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "f1600x2.h" -#include "fips202x2.h" - - -void thash(unsigned char *out, - const unsigned char *in, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t addrx2 [2*8] = { - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] - }; - thashx2(out, out, in, in, inblocks, ctx, addrx2); -} - -/** - * 2-way parallel version of thash; takes 2x as much input and output - */ -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2*8]) -{ - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the twoway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - for (int i = 0; i < SPX_N/8; i++) { - uint64_t x = load64(ctx->pub_seed + 8*i); - state[2*i] = x; - state[2*i+1] = x; - } - for (int i = 0; i < 4; i++) { - state[2*(SPX_N/8 + i)] = (((uint64_t)addrx2[1+2*i]) << 32) - | (uint64_t)addrx2[2*i]; - state[2*(SPX_N/8 + i) + 1] = (((uint64_t)addrx2[8+1+2*i]) << 32) - | (uint64_t)addrx2[8+2*i]; - } - - for (unsigned int i = 0; i < (SPX_N/8) * inblocks; i++) { - state[2*(SPX_N/8+4+i)] = load64(in0+8*i); - state[2*(SPX_N/8+4+i)+1] = load64(in1+8*i); - } - - /* Domain separator and padding. */ - state[2*16] = 0x80ULL << 56; - state[2*16+1] = 0x80ULL << 56; - - state[2*((SPX_N/8)*(1+inblocks)+4)] ^= 0x1f; - state[2*((SPX_N/8)*(1+inblocks)+4)+1] ^= 0x1f; - - f1600x2(state); - - for (int i = 0; i < SPX_N/8; i++) { - store64(out0 + 8*i, state[2*i]); - store64(out1 + 8*i, state[2*i+1]); - } - } else { - SPX_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - SPX_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx2 + 0*8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx2 + 1*8, SPX_ADDR_BYTES); - memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); - memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); - - shake256x2(out0, out1, SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - } -} diff --git a/sphincsplus/shake-a64/thashx2.h b/sphincsplus/shake-a64/thashx2.h deleted file mode 100644 index bde4f59..0000000 --- a/sphincsplus/shake-a64/thashx2.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SPX_THASHX2_H -#define SPX_THASHX2_H - -#include -#include "context.h" -#include "params.h" - -#define thashx2 SPX_NAMESPACE(thashx2) -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2*8]); - -#endif diff --git a/sphincsplus/shake-a64/utils.c b/sphincsplus/shake-a64/utils.c deleted file mode 120000 index e8ef6eb..0000000 --- a/sphincsplus/shake-a64/utils.c +++ /dev/null @@ -1 +0,0 @@ -../ref/utils.c \ No newline at end of file diff --git a/sphincsplus/shake-a64/utils.h b/sphincsplus/shake-a64/utils.h deleted file mode 120000 index 51b0d39..0000000 --- a/sphincsplus/shake-a64/utils.h +++ /dev/null @@ -1 +0,0 @@ -../ref/utils.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/utilsx2.c b/sphincsplus/shake-a64/utilsx2.c deleted file mode 100644 index 7b75fb4..0000000 --- a/sphincsplus/shake-a64/utilsx2.c +++ /dev/null @@ -1,130 +0,0 @@ -#include - -#include "utils.h" -#include "utilsx2.h" -#include "params.h" -#include "thashx2.h" -#include "address.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx2 to be initialized to 2 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 2 consecutive nodes in the real tree. - * When we combine two logical nodes AB and WX, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(WX) - * - * When we get to the top level of the real tree (where there is only - * one logical node), we continue this operation one more time; the right - * most real node will by the actual root (and the other node will be - * garbage). We follow the same thashx2 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - */ -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx2)( - unsigned char* /* Where to write the leaves */, - const spx_ctx*, - uint32_t idx, void *info), - uint32_t tree_addrx2[2*8], - void *info) -{ - /* This is where we keep the intermediate nodes */ - SPX_VLA(unsigned char, stackx2, 2 * tree_height * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ - /* level, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1 << (tree_height-1)) - 1; - for (idx = 0;; idx++) { - unsigned char current[2*SPX_N]; /* Current logical node */ - gen_leafx2( current, ctx, 2*idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h=0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 1) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1*SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 2 - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1*SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf&1)^1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 2 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - int j; - internal_idx_offset >>= 1; - for (j = 0; j < 2; j++) { - set_tree_height(tree_addrx2 + j*8, h + 1); - set_tree_index(tree_addrx2 + j*8, - (2/2) * (internal_idx&~1) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx2[h * 2 * SPX_N]; - thashx2( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - &left [0 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addrx2); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); - } -} diff --git a/sphincsplus/shake-a64/utilsx2.h b/sphincsplus/shake-a64/utilsx2.h deleted file mode 100644 index 3fcfb9d..0000000 --- a/sphincsplus/shake-a64/utilsx2.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_UTILSX2_H -#define SPX_UTILSX2_H - -#include -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses SIMD to compute internal nodes 2 at a time (in - * parallel) - */ -#define treehashx2 SPX_NAMESPACE(treehashx2) -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx2)( - unsigned char* /* Where to write the leaves */, - const spx_ctx* /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx2[2*8], void *info); - -#endif diff --git a/sphincsplus/shake-a64/wots.c b/sphincsplus/shake-a64/wots.c deleted file mode 100644 index ef0235b..0000000 --- a/sphincsplus/shake-a64/wots.c +++ /dev/null @@ -1,261 +0,0 @@ -#include -#include - -#include "utils.h" -#include "utilsx2.h" -#include "hash.h" -#include "hashx2.h" -#include "thashx2.h" -#include "wots.h" -#include "wotsx2.h" -#include "address.h" -#include "params.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) -{ - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8*2]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr} */ - for (j = 0; j < 2; j++) { - memcpy(addrs+j*8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN*SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 2) { - for (j = 0; j < 2 && i+j < SPX_WOTS_LEN; j++) { - idx = idxs[i+j]; - set_chain_addr(addrs+j*8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 1; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i+watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs+j*8, k + start[idxs[i+j]]); - } - - thashx2(bufs[0], bufs[1], - bufs[0], bufs[1], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) -{ - int in = 0; - int out = 0; - unsigned char total; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) -{ - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) -{ - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) -{ - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 2 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x2 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0; - wots_sign_index = 0; - } - - for (j = 0; j < 2; j++) { - set_keypair_addr( leaf_addr + j*8, leaf_idx + j ); - set_keypair_addr( pk_addr + j*8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 2; j++) { - set_chain_addr(leaf_addr + j*8, i); - set_hash_addr(leaf_addr + j*8, 0); - set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx2(buffer + 0*wots_offset, - buffer + 1*wots_offset, - ctx, leaf_addr); - for (j = 0; j < 2; j++) { - set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k=0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index*wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) break; - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 2; j++) { - set_hash_addr(leaf_addr + j*8, k); - } - thashx2(buffer + 0*wots_offset, - buffer + 1*wots_offset, - buffer + 0*wots_offset, - buffer + 1*wots_offset, - 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx2(dest + 0*SPX_N, - dest + 1*SPX_N, - pk_buffer + 0*wots_offset, - pk_buffer + 1*wots_offset, - SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/sphincsplus/shake-a64/wots.h b/sphincsplus/shake-a64/wots.h deleted file mode 120000 index 8c327ea..0000000 --- a/sphincsplus/shake-a64/wots.h +++ /dev/null @@ -1 +0,0 @@ -../ref/wots.h \ No newline at end of file diff --git a/sphincsplus/shake-a64/wotsx2.h b/sphincsplus/shake-a64/wotsx2.h deleted file mode 100644 index 6237737..0000000 --- a/sphincsplus/shake-a64/wotsx2.h +++ /dev/null @@ -1,40 +0,0 @@ -#if !defined( WOTSX2_H_ ) -#define WOTSX2_H_ - -#include -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx2 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x2 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[2*8]; - uint32_t pk_addr[2*8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ - info.wots_sig = 0; \ - info.wots_sign_leaf = ~0; \ - info.wots_steps = step_buffer; \ - int i; \ - for (i=0; i<2; i++) { \ - memcpy( &info.leaf_addr[8*i], addr, 32 ); \ - memcpy( &info.pk_addr[8*i], addr, 32 ); \ - } \ -} - -#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX2_H_ */ diff --git a/sphincsplus/shake-avx2/.gitignore b/sphincsplus/shake-avx2/.gitignore deleted file mode 100644 index 20d83ac..0000000 --- a/sphincsplus/shake-avx2/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -test/* -!test/*.c -PQCsignKAT_*.rsp -PQCsignKAT_*.req -PQCgenKAT_sign -keccak4x/KeccakP-1600-times4-SIMD256.o \ No newline at end of file diff --git a/sphincsplus/shake-avx2/Makefile b/sphincsplus/shake-avx2/Makefile deleted file mode 100644 index fa8421c..0000000 --- a/sphincsplus/shake-avx2/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -PARAMS = sphincs-shake-128f -THASH = robust - -CC = /usr/bin/gcc -CFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3 -std=c99 -march=native -fomit-frame-pointer -flto -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) - -SOURCES = hash_shake.c hash_shakex4.c thash_shake_$(THASH).c thash_shake_$(THASH)x4.c address.c randombytes.c merkle.c wots.c utils.c utilsx4.c fors.c sign.c fips202.c fips202x4.c keccak4x/KeccakP-1600-times4-SIMD256.o -HEADERS = params.h hash.h hashx4.h thash.h thashx4.h address.h randombytes.h merkle.h wots.h utils.h utilsx4.h fors.h api.h fips202.h fips202x4.h - -DET_SOURCES = $(SOURCES:randombytes.%=rng.%) -DET_HEADERS = $(HEADERS:randombytes.%=rng.%) - -TESTS = test/fors \ - test/spx \ - test/thashx4 \ - -BENCHMARK = test/benchmark - -.PHONY: clean test benchmark - -default: PQCgenKAT_sign - -all: PQCgenKAT_sign tests benchmarks - -tests: $(TESTS) - -test: $(TESTS:=.exec) - -benchmarks: $(BENCHMARK) - -benchmark: $(BENCHMARK:=.exec) - -PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) - $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto - -test/%: test/%.c $(SOURCES) $(HEADERS) - $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) - -test/%.exec: test/% - @$< - -keccak4x/KeccakP-1600-times4-SIMD256.o: keccak4x/align.h \ - keccak4x/brg_endian.h \ - keccak4x/KeccakP-1600-times4-SIMD256.c \ - keccak4x/KeccakP-1600-times4-SnP.h \ - keccak4x/KeccakP-1600-unrolling.macros \ - keccak4x/SIMD256-config.h - $(CC) $(CFLAGS) -c keccak4x/KeccakP-1600-times4-SIMD256.c -o $@ - -clean: - -$(RM) keccak4x/KeccakP-1600-times4-SIMD256.o - -$(RM) $(TESTS) - -$(RM) $(BENCHMARK) - -$(RM) PQCgenKAT_sign - -$(RM) PQCsignKAT_*.rsp - -$(RM) PQCsignKAT_*.req diff --git a/sphincsplus/shake-avx2/PQCgenKAT_sign.c b/sphincsplus/shake-avx2/PQCgenKAT_sign.c deleted file mode 120000 index a17dbe2..0000000 --- a/sphincsplus/shake-avx2/PQCgenKAT_sign.c +++ /dev/null @@ -1 +0,0 @@ -../ref/PQCgenKAT_sign.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/address.c b/sphincsplus/shake-avx2/address.c deleted file mode 120000 index 02c52c6..0000000 --- a/sphincsplus/shake-avx2/address.c +++ /dev/null @@ -1 +0,0 @@ -../ref/address.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/address.h b/sphincsplus/shake-avx2/address.h deleted file mode 120000 index e670da5..0000000 --- a/sphincsplus/shake-avx2/address.h +++ /dev/null @@ -1 +0,0 @@ -../ref/address.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/api.h b/sphincsplus/shake-avx2/api.h deleted file mode 120000 index ea89e0a..0000000 --- a/sphincsplus/shake-avx2/api.h +++ /dev/null @@ -1 +0,0 @@ -../ref/api.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/context.h b/sphincsplus/shake-avx2/context.h deleted file mode 100644 index 993c9ce..0000000 --- a/sphincsplus/shake-avx2/context.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#endif diff --git a/sphincsplus/shake-avx2/fips202.c b/sphincsplus/shake-avx2/fips202.c deleted file mode 120000 index da2fa42..0000000 --- a/sphincsplus/shake-avx2/fips202.c +++ /dev/null @@ -1 +0,0 @@ -../ref/fips202.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/fips202.h b/sphincsplus/shake-avx2/fips202.h deleted file mode 120000 index c759415..0000000 --- a/sphincsplus/shake-avx2/fips202.h +++ /dev/null @@ -1 +0,0 @@ -../ref/fips202.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/fips202x4.c b/sphincsplus/shake-avx2/fips202x4.c deleted file mode 100644 index b875467..0000000 --- a/sphincsplus/shake-avx2/fips202x4.c +++ /dev/null @@ -1,225 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) ((a << offset) ^ (a >> (64-offset))) - -static uint64_t load64(const unsigned char *x) -{ - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) -{ - unsigned int i; - - for(i=0; i<8; ++i) { - x[i] = u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) -{ - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) - { - for (i = 0; i < r / 8; ++i) - { - ss[4*i+0] ^= load64(m0 + 8 * i); - ss[4*i+1] ^= load64(m1 + 8 * i); - ss[4*i+2] ^= load64(m2 + 8 * i); - ss[4*i+3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) - { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) - { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) - { - ss[4*i+0] ^= load64(t0 + 8 * i); - ss[4*i+1] ^= load64(t1 + 8 * i); - ss[4*i+2] ^= load64(t2 + 8 * i); - ss[4*i+3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) -{ - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while(nblocks > 0) - { - KeccakF1600_StatePermute4x(s); - for(i=0;i<(r>>3);i++) - { - store64(h0+8*i, ss[4*i+0]); - store64(h1+8*i, ss[4*i+1]); - store64(h2+8*i, ss[4*i+2]); - store64(h3+8*i, ss[4*i+3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) -{ - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for(i=0;i<25;i++) - s[i] = _mm256_xor_si256(s[i], s[i]); - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen/SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; - out1 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; - out2 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; - out3 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; - - if(outlen%SHAKE128_RATE) - { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for(i=0;i - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/sphincsplus/shake-avx2/fors.c b/sphincsplus/shake-avx2/fors.c deleted file mode 100644 index 8b634f4..0000000 --- a/sphincsplus/shake-avx2/fors.c +++ /dev/null @@ -1,209 +0,0 @@ -#include -#include -#include - -#include "fors.h" -#include "utils.h" -#include "utilsx4.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "address.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) -{ - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4*8]) -{ - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) -{ - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4*8]) -{ - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4*8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) -{ - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j*8, addr_idx + j); - set_type(fors_leaf_addrx4 + j*8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0*SPX_N, - leaf + 1*SPX_N, - leaf + 2*SPX_N, - leaf + 3*SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j*8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0*SPX_N, - leaf + 1*SPX_N, - leaf + 2*SPX_N, - leaf + 3*SPX_N, - leaf + 0*SPX_N, - leaf + 1*SPX_N, - leaf + 2*SPX_N, - leaf + 3*SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) -{ - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= ((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) -{ - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4*8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i=0; i<4; i++) { - copy_keypair_addr(fors_tree_addr + 8*i, fors_addr); - set_type(fors_tree_addr + 8*i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8*i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i*SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) -{ - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i*SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/sphincsplus/shake-avx2/fors.h b/sphincsplus/shake-avx2/fors.h deleted file mode 120000 index 07156bd..0000000 --- a/sphincsplus/shake-avx2/fors.h +++ /dev/null @@ -1 +0,0 @@ -../ref/fors.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/hash.h b/sphincsplus/shake-avx2/hash.h deleted file mode 120000 index cffc52b..0000000 --- a/sphincsplus/shake-avx2/hash.h +++ /dev/null @@ -1 +0,0 @@ -../ref/hash.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/hash_shake.c b/sphincsplus/shake-avx2/hash_shake.c deleted file mode 120000 index 1d9d0cd..0000000 --- a/sphincsplus/shake-avx2/hash_shake.c +++ /dev/null @@ -1 +0,0 @@ -../ref/hash_shake.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/hash_shakex4.c b/sphincsplus/shake-avx2/hash_shakex4.c deleted file mode 100644 index 93ee3cc..0000000 --- a/sphincsplus/shake-avx2/hash_shakex4.c +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "fips202x4.h" -#include "hashx4.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4*8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - - for (int i = 0; i < SPX_N/8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t*)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N/8+i] = _mm256_set_epi32( - addrx4[3*8+1+2*i], - addrx4[3*8+2*i], - addrx4[2*8+1+2*i], - addrx4[2*8+2*i], - addrx4[8+1+2*i], - addrx4[8+2*i], - addrx4[1+2*i], - addrx4[2*i] - ); - } - for (int i = 0; i < SPX_N/8; i++) { - state[SPX_N/8+i+4] = _mm256_set1_epi64x(((int64_t*)ctx->sk_seed)[i]); - } - - /* SHAKE domain separator and padding. */ - state[SPX_N/4+4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N/4+5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - // shift unsigned and then cast to avoid UB - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - for (int i = 0; i < SPX_N/8; i++) { - ((int64_t*)out0)[i] = _mm256_extract_epi64(state[i], 0); - ((int64_t*)out1)[i] = _mm256_extract_epi64(state[i], 1); - ((int64_t*)out2)[i] = _mm256_extract_epi64(state[i], 2); - ((int64_t*)out3)[i] = _mm256_extract_epi64(state[i], 3); - } -} diff --git a/sphincsplus/shake-avx2/hashx4.h b/sphincsplus/shake-avx2/hashx4.h deleted file mode 100644 index 1c19618..0000000 --- a/sphincsplus/shake-avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4*8]); - -#endif diff --git a/sphincsplus/shake-avx2/keccak4x/KeccakP-1600-times4-SIMD256.c b/sphincsplus/shake-avx2/keccak4x/KeccakP-1600-times4-SIMD256.c deleted file mode 100644 index 7a0428f..0000000 --- a/sphincsplus/shake-avx2/keccak4x/KeccakP-1600-times4-SIMD256.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* -Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, -Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby -denoted as "the implementer". - -For more information, feedback or questions, please refer to our websites: -http://keccak.noekeon.org/ -http://keyak.noekeon.org/ -http://ketje.noekeon.org/ - -To the extent possible under law, the implementer has waived all copyright -and related or neighboring rights to the source code in this file. -http://creativecommons.org/publicdomain/zero/1.0/ -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "align.h" -#include "KeccakP-1600-times4-SnP.h" -#include "SIMD256-config.h" - -#include "brg_endian.h" -#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN) -#error Expecting a little-endian platform -#endif - -typedef unsigned char UINT8; -typedef unsigned long long int UINT64; -typedef __m128i V128; -typedef __m256i V256; - -#define laneIndex(instanceIndex, lanePosition) ((lanePosition)*4 + instanceIndex) - -#if defined(KeccakP1600times4_useAVX2) - #define ANDnu256(a, b) _mm256_andnot_si256(a, b) - #define CONST256(a) _mm256_load_si256((const V256 *)&(a)) - #define CONST256_64(a) (V256)_mm256_broadcast_sd((const double*)(&a)) - #define LOAD256(a) _mm256_load_si256((const V256 *)&(a)) - #define LOAD256u(a) _mm256_loadu_si256((const V256 *)&(a)) - #define LOAD4_64(a, b, c, d) _mm256_set_epi64x((UINT64)(a), (UINT64)(b), (UINT64)(c), (UINT64)(d)) - #define ROL64in256(d, a, o) d = _mm256_or_si256(_mm256_slli_epi64(a, o), _mm256_srli_epi64(a, 64-(o))) - #define ROL64in256_8(d, a) d = _mm256_shuffle_epi8(a, CONST256(rho8)) - #define ROL64in256_56(d, a) d = _mm256_shuffle_epi8(a, CONST256(rho56)) -static const UINT64 rho8[4] = {0x0605040302010007, 0x0E0D0C0B0A09080F, 0x1615141312111017, 0x1E1D1C1B1A19181F}; -static const UINT64 rho56[4] = {0x0007060504030201, 0x080F0E0D0C0B0A09, 0x1017161514131211, 0x181F1E1D1C1B1A19}; - #define STORE256(a, b) _mm256_store_si256((V256 *)&(a), b) - #define STORE256u(a, b) _mm256_storeu_si256((V256 *)&(a), b) - #define STORE2_128(ah, al, v) _mm256_storeu2_m128d((V128*)&(ah), (V128*)&(al), v) - #define XOR256(a, b) _mm256_xor_si256(a, b) - #define XOReq256(a, b) a = _mm256_xor_si256(a, b) - #define UNPACKL( a, b ) _mm256_unpacklo_epi64((a), (b)) - #define UNPACKH( a, b ) _mm256_unpackhi_epi64((a), (b)) - #define PERM128( a, b, c ) (V256)_mm256_permute2f128_ps((__m256)(a), (__m256)(b), c) - #define SHUFFLE64( a, b, c ) (V256)_mm256_shuffle_pd((__m256d)(a), (__m256d)(b), c) - - #define UNINTLEAVE() lanesL01 = UNPACKL( lanes0, lanes1 ), \ - lanesH01 = UNPACKH( lanes0, lanes1 ), \ - lanesL23 = UNPACKL( lanes2, lanes3 ), \ - lanesH23 = UNPACKH( lanes2, lanes3 ), \ - lanes0 = PERM128( lanesL01, lanesL23, 0x20 ), \ - lanes2 = PERM128( lanesL01, lanesL23, 0x31 ), \ - lanes1 = PERM128( lanesH01, lanesH23, 0x20 ), \ - lanes3 = PERM128( lanesH01, lanesH23, 0x31 ) - - #define INTLEAVE() lanesL01 = PERM128( lanes0, lanes2, 0x20 ), \ - lanesH01 = PERM128( lanes1, lanes3, 0x20 ), \ - lanesL23 = PERM128( lanes0, lanes2, 0x31 ), \ - lanesH23 = PERM128( lanes1, lanes3, 0x31 ), \ - lanes0 = SHUFFLE64( lanesL01, lanesH01, 0x00 ), \ - lanes1 = SHUFFLE64( lanesL01, lanesH01, 0x0F ), \ - lanes2 = SHUFFLE64( lanesL23, lanesH23, 0x00 ), \ - lanes3 = SHUFFLE64( lanesL23, lanesH23, 0x0F ) - -#endif - -#define SnP_laneLengthInBytes 8 - -void KeccakP1600times4_InitializeAll(void *states) -{ - memset(states, 0, KeccakP1600times4_statesSizeInBytes); -} - -void KeccakP1600times4_AddBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length) -{ - unsigned int sizeLeft = length; - unsigned int lanePosition = offset/SnP_laneLengthInBytes; - unsigned int offsetInLane = offset%SnP_laneLengthInBytes; - const unsigned char *curData = data; - UINT64 *statesAsLanes = (UINT64 *)states; - - if ((sizeLeft > 0) && (offsetInLane != 0)) { - unsigned int bytesInLane = SnP_laneLengthInBytes - offsetInLane; - UINT64 lane = 0; - if (bytesInLane > sizeLeft) - bytesInLane = sizeLeft; - memcpy((unsigned char*)&lane + offsetInLane, curData, bytesInLane); - statesAsLanes[laneIndex(instanceIndex, lanePosition)] ^= lane; - sizeLeft -= bytesInLane; - lanePosition++; - curData += bytesInLane; - } - - while(sizeLeft >= SnP_laneLengthInBytes) { - UINT64 lane = *((const UINT64*)curData); - statesAsLanes[laneIndex(instanceIndex, lanePosition)] ^= lane; - sizeLeft -= SnP_laneLengthInBytes; - lanePosition++; - curData += SnP_laneLengthInBytes; - } - - if (sizeLeft > 0) { - UINT64 lane = 0; - memcpy(&lane, curData, sizeLeft); - statesAsLanes[laneIndex(instanceIndex, lanePosition)] ^= lane; - } -} - -void KeccakP1600times4_AddLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset) -{ - V256 *stateAsLanes = (V256 *)states; - unsigned int i; - const UINT64 *curData0 = (const UINT64 *)data; - const UINT64 *curData1 = (const UINT64 *)(data+laneOffset*SnP_laneLengthInBytes); - const UINT64 *curData2 = (const UINT64 *)(data+laneOffset*2*SnP_laneLengthInBytes); - const UINT64 *curData3 = (const UINT64 *)(data+laneOffset*3*SnP_laneLengthInBytes); - V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; - - #define Xor_In( argIndex ) XOReq256(stateAsLanes[argIndex], LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) - - #define Xor_In4( argIndex ) lanes0 = LOAD256u( curData0[argIndex]),\ - lanes1 = LOAD256u( curData1[argIndex]),\ - lanes2 = LOAD256u( curData2[argIndex]),\ - lanes3 = LOAD256u( curData3[argIndex]),\ - INTLEAVE(),\ - XOReq256( stateAsLanes[argIndex+0], lanes0 ),\ - XOReq256( stateAsLanes[argIndex+1], lanes1 ),\ - XOReq256( stateAsLanes[argIndex+2], lanes2 ),\ - XOReq256( stateAsLanes[argIndex+3], lanes3 ) - - if ( laneCount >= 16 ) { - Xor_In4( 0 ); - Xor_In4( 4 ); - Xor_In4( 8 ); - Xor_In4( 12 ); - if ( laneCount >= 20 ) { - Xor_In4( 16 ); - for(i=20; i 0) && (offsetInLane != 0)) { - unsigned int bytesInLane = SnP_laneLengthInBytes - offsetInLane; - if (bytesInLane > sizeLeft) - bytesInLane = sizeLeft; - memcpy( ((unsigned char *)&statesAsLanes[laneIndex(instanceIndex, lanePosition)]) + offsetInLane, curData, bytesInLane); - sizeLeft -= bytesInLane; - lanePosition++; - curData += bytesInLane; - } - - while(sizeLeft >= SnP_laneLengthInBytes) { - UINT64 lane = *((const UINT64*)curData); - statesAsLanes[laneIndex(instanceIndex, lanePosition)] = lane; - sizeLeft -= SnP_laneLengthInBytes; - lanePosition++; - curData += SnP_laneLengthInBytes; - } - - if (sizeLeft > 0) { - memcpy(&statesAsLanes[laneIndex(instanceIndex, lanePosition)], curData, sizeLeft); - } -} - -void KeccakP1600times4_OverwriteLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset) -{ - V256 *stateAsLanes = (V256 *)states; - unsigned int i; - const UINT64 *curData0 = (const UINT64 *)data; - const UINT64 *curData1 = (const UINT64 *)(data+laneOffset*SnP_laneLengthInBytes); - const UINT64 *curData2 = (const UINT64 *)(data+laneOffset*2*SnP_laneLengthInBytes); - const UINT64 *curData3 = (const UINT64 *)(data+laneOffset*3*SnP_laneLengthInBytes); - V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; - - #define OverWr( argIndex ) STORE256(stateAsLanes[argIndex], LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) - - #define OverWr4( argIndex ) lanes0 = LOAD256u( curData0[argIndex]),\ - lanes1 = LOAD256u( curData1[argIndex]),\ - lanes2 = LOAD256u( curData2[argIndex]),\ - lanes3 = LOAD256u( curData3[argIndex]),\ - INTLEAVE(),\ - STORE256( stateAsLanes[argIndex+0], lanes0 ),\ - STORE256( stateAsLanes[argIndex+1], lanes1 ),\ - STORE256( stateAsLanes[argIndex+2], lanes2 ),\ - STORE256( stateAsLanes[argIndex+3], lanes3 ) - - if ( laneCount >= 16 ) { - OverWr4( 0 ); - OverWr4( 4 ); - OverWr4( 8 ); - OverWr4( 12 ); - if ( laneCount >= 20 ) { - OverWr4( 16 ); - for(i=20; i= SnP_laneLengthInBytes) { - statesAsLanes[laneIndex(instanceIndex, lanePosition)] = 0; - sizeLeft -= SnP_laneLengthInBytes; - lanePosition++; - } - - if (sizeLeft > 0) { - memset(&statesAsLanes[laneIndex(instanceIndex, lanePosition)], 0, sizeLeft); - } -} - -void KeccakP1600times4_ExtractBytes(const void *states, unsigned int instanceIndex, unsigned char *data, unsigned int offset, unsigned int length) -{ - unsigned int sizeLeft = length; - unsigned int lanePosition = offset/SnP_laneLengthInBytes; - unsigned int offsetInLane = offset%SnP_laneLengthInBytes; - unsigned char *curData = data; - const UINT64 *statesAsLanes = (const UINT64 *)states; - - if ((sizeLeft > 0) && (offsetInLane != 0)) { - unsigned int bytesInLane = SnP_laneLengthInBytes - offsetInLane; - if (bytesInLane > sizeLeft) - bytesInLane = sizeLeft; - memcpy( curData, ((unsigned char *)&statesAsLanes[laneIndex(instanceIndex, lanePosition)]) + offsetInLane, bytesInLane); - sizeLeft -= bytesInLane; - lanePosition++; - curData += bytesInLane; - } - - while(sizeLeft >= SnP_laneLengthInBytes) { - *(UINT64*)curData = statesAsLanes[laneIndex(instanceIndex, lanePosition)]; - sizeLeft -= SnP_laneLengthInBytes; - lanePosition++; - curData += SnP_laneLengthInBytes; - } - - if (sizeLeft > 0) { - memcpy( curData, &statesAsLanes[laneIndex(instanceIndex, lanePosition)], sizeLeft); - } -} - -void KeccakP1600times4_ExtractLanesAll(const void *states, unsigned char *data, unsigned int laneCount, unsigned int laneOffset) -{ - UINT64 *curData0 = (UINT64 *)data; - UINT64 *curData1 = (UINT64 *)(data+laneOffset*1*SnP_laneLengthInBytes); - UINT64 *curData2 = (UINT64 *)(data+laneOffset*2*SnP_laneLengthInBytes); - UINT64 *curData3 = (UINT64 *)(data+laneOffset*3*SnP_laneLengthInBytes); - - const V256 *stateAsLanes = (const V256 *)states; - const UINT64 *stateAsLanes64 = (const UINT64*)states; - V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; - unsigned int i; - - #define Extr( argIndex ) curData0[argIndex] = stateAsLanes64[4*(argIndex)], \ - curData1[argIndex] = stateAsLanes64[4*(argIndex)+1], \ - curData2[argIndex] = stateAsLanes64[4*(argIndex)+2], \ - curData3[argIndex] = stateAsLanes64[4*(argIndex)+3] - - #define Extr4( argIndex ) lanes0 = LOAD256( stateAsLanes[argIndex+0] ), \ - lanes1 = LOAD256( stateAsLanes[argIndex+1] ), \ - lanes2 = LOAD256( stateAsLanes[argIndex+2] ), \ - lanes3 = LOAD256( stateAsLanes[argIndex+3] ), \ - UNINTLEAVE(), \ - STORE256u( curData0[argIndex], lanes0 ), \ - STORE256u( curData1[argIndex], lanes1 ), \ - STORE256u( curData2[argIndex], lanes2 ), \ - STORE256u( curData3[argIndex], lanes3 ) - - if ( laneCount >= 16 ) { - Extr4( 0 ); - Extr4( 4 ); - Extr4( 8 ); - Extr4( 12 ); - if ( laneCount >= 20 ) { - Extr4( 16 ); - for(i=20; i 0) && (offsetInLane != 0)) { - unsigned int bytesInLane = SnP_laneLengthInBytes - offsetInLane; - UINT64 lane = statesAsLanes[laneIndex(instanceIndex, lanePosition)] >> (8 * offsetInLane); - if (bytesInLane > sizeLeft) - bytesInLane = sizeLeft; - sizeLeft -= bytesInLane; - do { - *(curOutput++) = *(curInput++) ^ (unsigned char)lane; - lane >>= 8; - } while ( --bytesInLane != 0); - lanePosition++; - } - - while(sizeLeft >= SnP_laneLengthInBytes) { - *((UINT64*)curOutput) = *((UINT64*)curInput) ^ statesAsLanes[laneIndex(instanceIndex, lanePosition)]; - sizeLeft -= SnP_laneLengthInBytes; - lanePosition++; - curInput += SnP_laneLengthInBytes; - curOutput += SnP_laneLengthInBytes; - } - - if (sizeLeft != 0) { - UINT64 lane = statesAsLanes[laneIndex(instanceIndex, lanePosition)]; - do { - *(curOutput++) = *(curInput++) ^ (unsigned char)lane; - lane >>= 8; - } while ( --sizeLeft != 0); - } -} - -void KeccakP1600times4_ExtractAndAddLanesAll(const void *states, const unsigned char *input, unsigned char *output, unsigned int laneCount, unsigned int laneOffset) -{ - const UINT64 *curInput0 = (UINT64 *)input; - const UINT64 *curInput1 = (UINT64 *)(input+laneOffset*1*SnP_laneLengthInBytes); - const UINT64 *curInput2 = (UINT64 *)(input+laneOffset*2*SnP_laneLengthInBytes); - const UINT64 *curInput3 = (UINT64 *)(input+laneOffset*3*SnP_laneLengthInBytes); - UINT64 *curOutput0 = (UINT64 *)output; - UINT64 *curOutput1 = (UINT64 *)(output+laneOffset*1*SnP_laneLengthInBytes); - UINT64 *curOutput2 = (UINT64 *)(output+laneOffset*2*SnP_laneLengthInBytes); - UINT64 *curOutput3 = (UINT64 *)(output+laneOffset*3*SnP_laneLengthInBytes); - - const V256 *stateAsLanes = (const V256 *)states; - const UINT64 *stateAsLanes64 = (const UINT64*)states; - V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; - unsigned int i; - - #define ExtrXor( argIndex ) \ - curOutput0[argIndex] = curInput0[argIndex] ^ stateAsLanes64[4*(argIndex)],\ - curOutput1[argIndex] = curInput1[argIndex] ^ stateAsLanes64[4*(argIndex)+1],\ - curOutput2[argIndex] = curInput2[argIndex] ^ stateAsLanes64[4*(argIndex)+2],\ - curOutput3[argIndex] = curInput3[argIndex] ^ stateAsLanes64[4*(argIndex)+3] - - #define ExtrXor4( argIndex ) \ - lanes0 = LOAD256( stateAsLanes[argIndex+0] ),\ - lanes1 = LOAD256( stateAsLanes[argIndex+1] ),\ - lanes2 = LOAD256( stateAsLanes[argIndex+2] ),\ - lanes3 = LOAD256( stateAsLanes[argIndex+3] ),\ - UNINTLEAVE(),\ - lanesL01 = LOAD256u( curInput0[argIndex]),\ - lanesH01 = LOAD256u( curInput1[argIndex]),\ - lanesL23 = LOAD256u( curInput2[argIndex]),\ - lanesH23 = LOAD256u( curInput3[argIndex]),\ - XOReq256( lanes0, lanesL01 ),\ - XOReq256( lanes1, lanesH01 ),\ - XOReq256( lanes2, lanesL23 ),\ - XOReq256( lanes3, lanesH23 ),\ - STORE256u( curOutput0[argIndex], lanes0 ),\ - STORE256u( curOutput1[argIndex], lanes1 ),\ - STORE256u( curOutput2[argIndex], lanes2 ),\ - STORE256u( curOutput3[argIndex], lanes3 ) - - if ( laneCount >= 16 ) { - ExtrXor4( 0 ); - ExtrXor4( 4 ); - ExtrXor4( 8 ); - ExtrXor4( 12 ); - if ( laneCount >= 20 ) { - ExtrXor4( 16 ); - for(i=20; i= (laneOffsetParallel*3 + laneCount)*8) { - V256 *stateAsLanes = (V256 *)states; - V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; - #define Xor_In( argIndex ) \ - XOReq256(stateAsLanes[argIndex], LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) - #define Xor_In4( argIndex ) \ - lanes0 = LOAD256u( curData0[argIndex]),\ - lanes1 = LOAD256u( curData1[argIndex]),\ - lanes2 = LOAD256u( curData2[argIndex]),\ - lanes3 = LOAD256u( curData3[argIndex]),\ - INTLEAVE(),\ - XOReq256( stateAsLanes[argIndex+0], lanes0 ),\ - XOReq256( stateAsLanes[argIndex+1], lanes1 ),\ - XOReq256( stateAsLanes[argIndex+2], lanes2 ),\ - XOReq256( stateAsLanes[argIndex+3], lanes3 ) - Xor_In4( 0 ); - Xor_In4( 4 ); - Xor_In4( 8 ); - Xor_In4( 12 ); - Xor_In4( 16 ); - Xor_In( 20 ); - #undef Xor_In - #undef Xor_In4 - KeccakP1600times4_PermuteAll_24rounds(states); - curData0 += laneOffsetSerial; - curData1 += laneOffsetSerial; - curData2 += laneOffsetSerial; - curData3 += laneOffsetSerial; - dataByteLen -= laneOffsetSerial*8; - } - return (const unsigned char *)curData0 - dataStart; -#else -// unsigned int i; - const unsigned char *dataStart = data; - const UINT64 *curData0 = (const UINT64 *)data; - const UINT64 *curData1 = (const UINT64 *)(data+laneOffsetParallel*1*SnP_laneLengthInBytes); - const UINT64 *curData2 = (const UINT64 *)(data+laneOffsetParallel*2*SnP_laneLengthInBytes); - const UINT64 *curData3 = (const UINT64 *)(data+laneOffsetParallel*3*SnP_laneLengthInBytes); - V256 *statesAsLanes = (V256 *)states; - declareABCDE - - copyFromState(A, statesAsLanes) - while(dataByteLen >= (laneOffsetParallel*3 + laneCount)*8) { - #define XOR_In( Xxx, argIndex ) \ - XOReq256(Xxx, LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) - XOR_In( Aba, 0 ); - XOR_In( Abe, 1 ); - XOR_In( Abi, 2 ); - XOR_In( Abo, 3 ); - XOR_In( Abu, 4 ); - XOR_In( Aga, 5 ); - XOR_In( Age, 6 ); - XOR_In( Agi, 7 ); - XOR_In( Ago, 8 ); - XOR_In( Agu, 9 ); - XOR_In( Aka, 10 ); - XOR_In( Ake, 11 ); - XOR_In( Aki, 12 ); - XOR_In( Ako, 13 ); - XOR_In( Aku, 14 ); - XOR_In( Ama, 15 ); - XOR_In( Ame, 16 ); - XOR_In( Ami, 17 ); - XOR_In( Amo, 18 ); - XOR_In( Amu, 19 ); - XOR_In( Asa, 20 ); - #undef XOR_In - rounds24 - curData0 += laneOffsetSerial; - curData1 += laneOffsetSerial; - curData2 += laneOffsetSerial; - curData3 += laneOffsetSerial; - dataByteLen -= laneOffsetSerial*8; - } - copyToState(statesAsLanes, A) - return (const unsigned char *)curData0 - dataStart; -#endif - } - else { -// unsigned int i; - const unsigned char *dataStart = data; - - while(dataByteLen >= (laneOffsetParallel*3 + laneCount)*8) { - KeccakP1600times4_AddLanesAll(states, data, laneCount, laneOffsetParallel); - KeccakP1600times4_PermuteAll_24rounds(states); - data += laneOffsetSerial*8; - dataByteLen -= laneOffsetSerial*8; - } - return data - dataStart; - } -} - -size_t KeccakP1600times4_12rounds_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen) -{ - if (laneCount == 21) { -#if 0 - const unsigned char *dataStart = data; - const UINT64 *curData0 = (const UINT64 *)data; - const UINT64 *curData1 = (const UINT64 *)(data+laneOffsetParallel*1*SnP_laneLengthInBytes); - const UINT64 *curData2 = (const UINT64 *)(data+laneOffsetParallel*2*SnP_laneLengthInBytes); - const UINT64 *curData3 = (const UINT64 *)(data+laneOffsetParallel*3*SnP_laneLengthInBytes); - - while(dataByteLen >= (laneOffsetParallel*3 + laneCount)*8) { - V256 *stateAsLanes = states; - V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; - #define Xor_In( argIndex ) \ - XOReq256(stateAsLanes[argIndex], LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) - #define Xor_In4( argIndex ) \ - lanes0 = LOAD256u( curData0[argIndex]),\ - lanes1 = LOAD256u( curData1[argIndex]),\ - lanes2 = LOAD256u( curData2[argIndex]),\ - lanes3 = LOAD256u( curData3[argIndex]),\ - INTLEAVE(),\ - XOReq256( stateAsLanes[argIndex+0], lanes0 ),\ - XOReq256( stateAsLanes[argIndex+1], lanes1 ),\ - XOReq256( stateAsLanes[argIndex+2], lanes2 ),\ - XOReq256( stateAsLanes[argIndex+3], lanes3 ) - Xor_In4( 0 ); - Xor_In4( 4 ); - Xor_In4( 8 ); - Xor_In4( 12 ); - Xor_In4( 16 ); - Xor_In( 20 ); - #undef Xor_In - #undef Xor_In4 - KeccakP1600times4_PermuteAll_12rounds(states); - curData0 += laneOffsetSerial; - curData1 += laneOffsetSerial; - curData2 += laneOffsetSerial; - curData3 += laneOffsetSerial; - dataByteLen -= laneOffsetSerial*8; - } - return (const unsigned char *)curData0 - dataStart; -#else -// unsigned int i; - const unsigned char *dataStart = data; - const UINT64 *curData0 = (const UINT64 *)data; - const UINT64 *curData1 = (const UINT64 *)(data+laneOffsetParallel*1*SnP_laneLengthInBytes); - const UINT64 *curData2 = (const UINT64 *)(data+laneOffsetParallel*2*SnP_laneLengthInBytes); - const UINT64 *curData3 = (const UINT64 *)(data+laneOffsetParallel*3*SnP_laneLengthInBytes); - V256 *statesAsLanes = states; - declareABCDE - - copyFromState(A, statesAsLanes) - while(dataByteLen >= (laneOffsetParallel*3 + laneCount)*8) { - #define XOR_In( Xxx, argIndex ) \ - XOReq256(Xxx, LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) - XOR_In( Aba, 0 ); - XOR_In( Abe, 1 ); - XOR_In( Abi, 2 ); - XOR_In( Abo, 3 ); - XOR_In( Abu, 4 ); - XOR_In( Aga, 5 ); - XOR_In( Age, 6 ); - XOR_In( Agi, 7 ); - XOR_In( Ago, 8 ); - XOR_In( Agu, 9 ); - XOR_In( Aka, 10 ); - XOR_In( Ake, 11 ); - XOR_In( Aki, 12 ); - XOR_In( Ako, 13 ); - XOR_In( Aku, 14 ); - XOR_In( Ama, 15 ); - XOR_In( Ame, 16 ); - XOR_In( Ami, 17 ); - XOR_In( Amo, 18 ); - XOR_In( Amu, 19 ); - XOR_In( Asa, 20 ); - #undef XOR_In - rounds12 - curData0 += laneOffsetSerial; - curData1 += laneOffsetSerial; - curData2 += laneOffsetSerial; - curData3 += laneOffsetSerial; - dataByteLen -= laneOffsetSerial*8; - } - copyToState(statesAsLanes, A) - return (const unsigned char *)curData0 - dataStart; -#endif - } - else { -// unsigned int i; - const unsigned char *dataStart = data; - - while(dataByteLen >= (laneOffsetParallel*3 + laneCount)*8) { - KeccakP1600times4_AddLanesAll(states, data, laneCount, laneOffsetParallel); - KeccakP1600times4_PermuteAll_12rounds(states); - data += laneOffsetSerial*8; - dataByteLen -= laneOffsetSerial*8; - } - return data - dataStart; - } -} diff --git a/sphincsplus/shake-avx2/keccak4x/KeccakP-1600-times4-SnP.h b/sphincsplus/shake-avx2/keccak4x/KeccakP-1600-times4-SnP.h deleted file mode 100644 index 6033848..0000000 --- a/sphincsplus/shake-avx2/keccak4x/KeccakP-1600-times4-SnP.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, -Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby -denoted as "the implementer". - -For more information, feedback or questions, please refer to our websites: -http://keccak.noekeon.org/ -http://keyak.noekeon.org/ -http://ketje.noekeon.org/ - -To the extent possible under law, the implementer has waived all copyright -and related or neighboring rights to the source code in this file. -http://creativecommons.org/publicdomain/zero/1.0/ -*/ - -#ifndef _KeccakP_1600_times4_SnP_h_ -#define _KeccakP_1600_times4_SnP_h_ - -/** For the documentation, see PlSnP-documentation.h. - */ - -#include "SIMD256-config.h" - -#define KeccakP1600times4_implementation "256-bit SIMD implementation (" KeccakP1600times4_implementation_config ")" -#define KeccakP1600times4_statesSizeInBytes 800 -#define KeccakP1600times4_statesAlignment 32 -#define KeccakF1600times4_FastLoop_supported -#define KeccakP1600times4_12rounds_FastLoop_supported - -#include - -#define KeccakP1600times4_StaticInitialize() -void KeccakP1600times4_InitializeAll(void *states); -#define KeccakP1600times4_AddByte(states, instanceIndex, byte, offset) \ - ((unsigned char*)(states))[(instanceIndex)*8 + ((offset)/8)*4*8 + (offset)%8] ^= (byte) -void KeccakP1600times4_AddBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length); -void KeccakP1600times4_AddLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset); -void KeccakP1600times4_OverwriteBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length); -void KeccakP1600times4_OverwriteLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset); -void KeccakP1600times4_OverwriteWithZeroes(void *states, unsigned int instanceIndex, unsigned int byteCount); -void KeccakP1600times4_PermuteAll_12rounds(void *states); -void KeccakP1600times4_PermuteAll_24rounds(void *states); -void KeccakP1600times4_ExtractBytes(const void *states, unsigned int instanceIndex, unsigned char *data, unsigned int offset, unsigned int length); -void KeccakP1600times4_ExtractLanesAll(const void *states, unsigned char *data, unsigned int laneCount, unsigned int laneOffset); -void KeccakP1600times4_ExtractAndAddBytes(const void *states, unsigned int instanceIndex, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length); -void KeccakP1600times4_ExtractAndAddLanesAll(const void *states, const unsigned char *input, unsigned char *output, unsigned int laneCount, unsigned int laneOffset); -size_t KeccakF1600times4_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen); -size_t KeccakP1600times4_12rounds_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen); - -#endif diff --git a/sphincsplus/shake-avx2/keccak4x/KeccakP-1600-unrolling.macros b/sphincsplus/shake-avx2/keccak4x/KeccakP-1600-unrolling.macros deleted file mode 100644 index 3180bb0..0000000 --- a/sphincsplus/shake-avx2/keccak4x/KeccakP-1600-unrolling.macros +++ /dev/null @@ -1,198 +0,0 @@ -/* -Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, -Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby -denoted as "the implementer". - -For more information, feedback or questions, please refer to our websites: -http://keccak.noekeon.org/ -http://keyak.noekeon.org/ -http://ketje.noekeon.org/ - -To the extent possible under law, the implementer has waived all copyright -and related or neighboring rights to the source code in this file. -http://creativecommons.org/publicdomain/zero/1.0/ -*/ - -#if (defined(FullUnrolling)) -#define rounds24 \ - prepareTheta \ - thetaRhoPiChiIotaPrepareTheta( 0, A, E) \ - thetaRhoPiChiIotaPrepareTheta( 1, E, A) \ - thetaRhoPiChiIotaPrepareTheta( 2, A, E) \ - thetaRhoPiChiIotaPrepareTheta( 3, E, A) \ - thetaRhoPiChiIotaPrepareTheta( 4, A, E) \ - thetaRhoPiChiIotaPrepareTheta( 5, E, A) \ - thetaRhoPiChiIotaPrepareTheta( 6, A, E) \ - thetaRhoPiChiIotaPrepareTheta( 7, E, A) \ - thetaRhoPiChiIotaPrepareTheta( 8, A, E) \ - thetaRhoPiChiIotaPrepareTheta( 9, E, A) \ - thetaRhoPiChiIotaPrepareTheta(10, A, E) \ - thetaRhoPiChiIotaPrepareTheta(11, E, A) \ - thetaRhoPiChiIotaPrepareTheta(12, A, E) \ - thetaRhoPiChiIotaPrepareTheta(13, E, A) \ - thetaRhoPiChiIotaPrepareTheta(14, A, E) \ - thetaRhoPiChiIotaPrepareTheta(15, E, A) \ - thetaRhoPiChiIotaPrepareTheta(16, A, E) \ - thetaRhoPiChiIotaPrepareTheta(17, E, A) \ - thetaRhoPiChiIotaPrepareTheta(18, A, E) \ - thetaRhoPiChiIotaPrepareTheta(19, E, A) \ - thetaRhoPiChiIotaPrepareTheta(20, A, E) \ - thetaRhoPiChiIotaPrepareTheta(21, E, A) \ - thetaRhoPiChiIotaPrepareTheta(22, A, E) \ - thetaRhoPiChiIota(23, E, A) \ - -#define rounds12 \ - prepareTheta \ - thetaRhoPiChiIotaPrepareTheta(12, A, E) \ - thetaRhoPiChiIotaPrepareTheta(13, E, A) \ - thetaRhoPiChiIotaPrepareTheta(14, A, E) \ - thetaRhoPiChiIotaPrepareTheta(15, E, A) \ - thetaRhoPiChiIotaPrepareTheta(16, A, E) \ - thetaRhoPiChiIotaPrepareTheta(17, E, A) \ - thetaRhoPiChiIotaPrepareTheta(18, A, E) \ - thetaRhoPiChiIotaPrepareTheta(19, E, A) \ - thetaRhoPiChiIotaPrepareTheta(20, A, E) \ - thetaRhoPiChiIotaPrepareTheta(21, E, A) \ - thetaRhoPiChiIotaPrepareTheta(22, A, E) \ - thetaRhoPiChiIota(23, E, A) \ - -#elif (Unrolling == 12) -#define rounds24 \ - prepareTheta \ - for(i=0; i<24; i+=12) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \ - } \ - -#define rounds12 \ - prepareTheta \ - thetaRhoPiChiIotaPrepareTheta(12, A, E) \ - thetaRhoPiChiIotaPrepareTheta(13, E, A) \ - thetaRhoPiChiIotaPrepareTheta(14, A, E) \ - thetaRhoPiChiIotaPrepareTheta(15, E, A) \ - thetaRhoPiChiIotaPrepareTheta(16, A, E) \ - thetaRhoPiChiIotaPrepareTheta(17, E, A) \ - thetaRhoPiChiIotaPrepareTheta(18, A, E) \ - thetaRhoPiChiIotaPrepareTheta(19, E, A) \ - thetaRhoPiChiIotaPrepareTheta(20, A, E) \ - thetaRhoPiChiIotaPrepareTheta(21, E, A) \ - thetaRhoPiChiIotaPrepareTheta(22, A, E) \ - thetaRhoPiChiIota(23, E, A) \ - -#elif (Unrolling == 6) -#define rounds24 \ - prepareTheta \ - for(i=0; i<24; i+=6) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ - } \ - -#define rounds12 \ - prepareTheta \ - for(i=12; i<24; i+=6) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ - } \ - -#elif (Unrolling == 4) -#define rounds24 \ - prepareTheta \ - for(i=0; i<24; i+=4) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ - } \ - -#define rounds12 \ - prepareTheta \ - for(i=12; i<24; i+=4) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ - } \ - -#elif (Unrolling == 3) -#define rounds24 \ - prepareTheta \ - for(i=0; i<24; i+=3) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ - copyStateVariables(A, E) \ - } \ - -#define rounds12 \ - prepareTheta \ - for(i=12; i<24; i+=3) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ - thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ - copyStateVariables(A, E) \ - } \ - -#elif (Unrolling == 2) -#define rounds24 \ - prepareTheta \ - for(i=0; i<24; i+=2) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ - } \ - -#define rounds12 \ - prepareTheta \ - for(i=12; i<24; i+=2) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ - } \ - -#elif (Unrolling == 1) -#define rounds24 \ - prepareTheta \ - for(i=0; i<24; i++) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - copyStateVariables(A, E) \ - } \ - -#define rounds12 \ - prepareTheta \ - for(i=12; i<24; i++) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - copyStateVariables(A, E) \ - } \ - -#else -#error "Unrolling is not correctly specified!" -#endif - -#define roundsN(__nrounds) \ - prepareTheta \ - i = 24 - (__nrounds); \ - if ((i&1) != 0) { \ - thetaRhoPiChiIotaPrepareTheta(i, A, E) \ - copyStateVariables(A, E) \ - ++i; \ - } \ - for( /* empty */; i<24; i+=2) { \ - thetaRhoPiChiIotaPrepareTheta(i , A, E) \ - thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ - } diff --git a/sphincsplus/shake-avx2/keccak4x/SIMD256-config.h b/sphincsplus/shake-avx2/keccak4x/SIMD256-config.h deleted file mode 100644 index 1c65fe2..0000000 --- a/sphincsplus/shake-avx2/keccak4x/SIMD256-config.h +++ /dev/null @@ -1,3 +0,0 @@ -#define KeccakP1600times4_implementation_config "AVX2, all rounds unrolled" -#define KeccakP1600times4_fullUnrolling -#define KeccakP1600times4_useAVX2 diff --git a/sphincsplus/shake-avx2/keccak4x/align.h b/sphincsplus/shake-avx2/keccak4x/align.h deleted file mode 100644 index e29771e..0000000 --- a/sphincsplus/shake-avx2/keccak4x/align.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, -Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby -denoted as "the implementer". - -For more information, feedback or questions, please refer to our websites: -http://keccak.noekeon.org/ -http://keyak.noekeon.org/ -http://ketje.noekeon.org/ - -To the extent possible under law, the implementer has waived all copyright -and related or neighboring rights to the source code in this file. -http://creativecommons.org/publicdomain/zero/1.0/ -*/ - -#ifndef _align_h_ -#define _align_h_ - -/* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */ -#ifdef ALIGN -#undef ALIGN -#endif - -#if defined(__GNUC__) -#define ALIGN(x) __attribute__ ((aligned(x))) -#elif defined(_MSC_VER) -#define ALIGN(x) __declspec(align(x)) -#elif defined(__ARMCC_VERSION) -#define ALIGN(x) __align(x) -#else -#define ALIGN(x) -#endif - -#endif diff --git a/sphincsplus/shake-avx2/keccak4x/brg_endian.h b/sphincsplus/shake-avx2/keccak4x/brg_endian.h deleted file mode 100644 index 7226eb3..0000000 --- a/sphincsplus/shake-avx2/keccak4x/brg_endian.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The redistribution and use of this software (with or without changes) - is allowed without the payment of fees or royalties provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 20/12/2007 - Changes for ARM 9/9/2010 -*/ - -#ifndef _BRG_ENDIAN_H -#define _BRG_ENDIAN_H - -#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ -#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ - -#if 0 -/* Include files where endian defines and byteswap functions may reside */ -#if defined( __sun ) -# include -#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) -# include -#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \ - defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ ) -# include -#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ ) -# if !defined( __MINGW32__ ) && !defined( _AIX ) -# include -# if !defined( __BEOS__ ) -# include -# endif -# endif -#endif -#endif - -/* Now attempt to set the define for platform byte order using any */ -/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */ -/* seem to encompass most endian symbol definitions */ - -#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN ) -# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -# endif -#elif defined( BIG_ENDIAN ) -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -#elif defined( LITTLE_ENDIAN ) -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -#endif - -#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN ) -# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -# endif -#elif defined( _BIG_ENDIAN ) -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -#elif defined( _LITTLE_ENDIAN ) -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -#endif - -#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN ) -# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -# endif -#elif defined( __BIG_ENDIAN ) -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -#elif defined( __LITTLE_ENDIAN ) -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -#endif - -#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ ) -# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__ -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__ -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -# endif -#elif defined( __BIG_ENDIAN__ ) -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -#elif defined( __LITTLE_ENDIAN__ ) -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -#endif - -/* if the platform byte order could not be determined, then try to */ -/* set this define using common machine defines */ -#if !defined(PLATFORM_BYTE_ORDER) - -#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \ - defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \ - defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \ - defined( vax ) || defined( vms ) || defined( VMS ) || \ - defined( __VMS ) || defined( _M_X64 ) -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN - -#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \ - defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \ - defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \ - defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \ - defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \ - defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \ - defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN - -#elif defined(__arm__) -# ifdef __BIG_ENDIAN -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -# else -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -# endif -#elif 1 /* **** EDIT HERE IF NECESSARY **** */ -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -#elif 0 /* **** EDIT HERE IF NECESSARY **** */ -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -#else -# error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order -#endif - -#endif - -#endif diff --git a/sphincsplus/shake-avx2/merkle.c b/sphincsplus/shake-avx2/merkle.c deleted file mode 100644 index e3929d8..0000000 --- a/sphincsplus/shake-avx2/merkle.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" -#include "merkle.h" -#include "address.h" -#include "params.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx* ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) -{ - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4*8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j=0; j<4; j++) { - set_type(&tree_addrx4[8*j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8*j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8*j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8*j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8*j], wots_addr); - copy_subtree_addr(&info.pk_addr[8*j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) -{ - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/sphincsplus/shake-avx2/merkle.h b/sphincsplus/shake-avx2/merkle.h deleted file mode 120000 index 7d167ed..0000000 --- a/sphincsplus/shake-avx2/merkle.h +++ /dev/null @@ -1 +0,0 @@ -../ref/merkle.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/params.h b/sphincsplus/shake-avx2/params.h deleted file mode 120000 index 53133cc..0000000 --- a/sphincsplus/shake-avx2/params.h +++ /dev/null @@ -1 +0,0 @@ -../ref/params.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/params/params-sphincs-shake-128f.h b/sphincsplus/shake-avx2/params/params-sphincs-shake-128f.h deleted file mode 120000 index c65db98..0000000 --- a/sphincsplus/shake-avx2/params/params-sphincs-shake-128f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-128f.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/params/params-sphincs-shake-128s.h b/sphincsplus/shake-avx2/params/params-sphincs-shake-128s.h deleted file mode 120000 index 18671f7..0000000 --- a/sphincsplus/shake-avx2/params/params-sphincs-shake-128s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-128s.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/params/params-sphincs-shake-192f.h b/sphincsplus/shake-avx2/params/params-sphincs-shake-192f.h deleted file mode 120000 index d071e35..0000000 --- a/sphincsplus/shake-avx2/params/params-sphincs-shake-192f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-192f.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/params/params-sphincs-shake-192s.h b/sphincsplus/shake-avx2/params/params-sphincs-shake-192s.h deleted file mode 120000 index 267e2c8..0000000 --- a/sphincsplus/shake-avx2/params/params-sphincs-shake-192s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-192s.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/params/params-sphincs-shake-256f.h b/sphincsplus/shake-avx2/params/params-sphincs-shake-256f.h deleted file mode 120000 index 3b4743b..0000000 --- a/sphincsplus/shake-avx2/params/params-sphincs-shake-256f.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-256f.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/params/params-sphincs-shake-256s.h b/sphincsplus/shake-avx2/params/params-sphincs-shake-256s.h deleted file mode 120000 index 0795ee1..0000000 --- a/sphincsplus/shake-avx2/params/params-sphincs-shake-256s.h +++ /dev/null @@ -1 +0,0 @@ -../../ref/params/params-sphincs-shake-256s.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/randombytes.c b/sphincsplus/shake-avx2/randombytes.c deleted file mode 120000 index 59a42a5..0000000 --- a/sphincsplus/shake-avx2/randombytes.c +++ /dev/null @@ -1 +0,0 @@ -../ref/randombytes.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/randombytes.h b/sphincsplus/shake-avx2/randombytes.h deleted file mode 120000 index 055e443..0000000 --- a/sphincsplus/shake-avx2/randombytes.h +++ /dev/null @@ -1 +0,0 @@ -../ref/randombytes.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/rng.c b/sphincsplus/shake-avx2/rng.c deleted file mode 120000 index 6e2fdac..0000000 --- a/sphincsplus/shake-avx2/rng.c +++ /dev/null @@ -1 +0,0 @@ -../ref/rng.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/rng.h b/sphincsplus/shake-avx2/rng.h deleted file mode 120000 index d678c7c..0000000 --- a/sphincsplus/shake-avx2/rng.h +++ /dev/null @@ -1 +0,0 @@ -../ref/rng.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/shake_offsets.h b/sphincsplus/shake-avx2/shake_offsets.h deleted file mode 120000 index 8cfe4c0..0000000 --- a/sphincsplus/shake-avx2/shake_offsets.h +++ /dev/null @@ -1 +0,0 @@ -../ref/shake_offsets.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/sign.c b/sphincsplus/shake-avx2/sign.c deleted file mode 120000 index 42fea88..0000000 --- a/sphincsplus/shake-avx2/sign.c +++ /dev/null @@ -1 +0,0 @@ -../ref/sign.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/test/benchmark.c b/sphincsplus/shake-avx2/test/benchmark.c deleted file mode 100644 index a5767a4..0000000 --- a/sphincsplus/shake-avx2/test/benchmark.c +++ /dev/null @@ -1,161 +0,0 @@ -#define _POSIX_C_SOURCE 199309L - -#include -#include -#include - -#include "../api.h" -#include "../fors.h" -#include "../wots.h" -#include "../wotsx4.h" -#include "../params.h" -#include "../randombytes.h" - -#define SPX_MLEN 32 -#define NTESTS 10 - -static void wots_gen_pkx4(unsigned char *pk, const spx_ctx *ctx, - uint32_t addr[8]); - -static int cmp_llu(const void *a, const void*b) -{ - if(*(unsigned long long *)a < *(unsigned long long *)b) return -1; - if(*(unsigned long long *)a > *(unsigned long long *)b) return 1; - return 0; -} - -static unsigned long long median(unsigned long long *l, size_t llen) -{ - qsort(l,llen,sizeof(unsigned long long),cmp_llu); - - if(llen%2) return l[llen/2]; - else return (l[llen/2-1]+l[llen/2])/2; -} - -static void delta(unsigned long long *l, size_t llen) -{ - unsigned int i; - for(i = 0; i < llen - 1; i++) { - l[i] = l[i+1] - l[i]; - } -} - -static unsigned long long cpucycles(void) -{ - unsigned long long result; - __asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax" - : "=a" (result) :: "%rdx"); - return result; -} - -static void printfcomma (unsigned long long n) -{ - if (n < 1000) { - printf("%llu", n); - return; - } - printfcomma(n / 1000); - printf (",%03llu", n % 1000); -} - -static void printfalignedcomma (unsigned long long n, int len) -{ - unsigned long long ncopy = n; - int i = 0; - - while (ncopy > 9) { - len -= 1; - ncopy /= 10; - i += 1; // to account for commas - } - i = i/3 - 1; // to account for commas - for (; i < len; i++) { - printf(" "); - } - printfcomma(n); -} - -static void display_result(double result, unsigned long long *l, size_t llen, unsigned long long mul) -{ - unsigned long long med; - - result /= NTESTS; - delta(l, NTESTS + 1); - med = median(l, llen); - printf("avg. %11.2lf us (%2.2lf sec); median ", result, result / 1e6); - printfalignedcomma(med, 12); - printf(" cycles, %5llux: ", mul); - printfalignedcomma(mul*med, 12); - printf(" cycles\n"); -} - -#define MEASURE(TEXT, MUL, FNCALL)\ - printf(TEXT);\ - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);\ - for(i = 0; i < NTESTS; i++) {\ - t[i] = cpucycles();\ - FNCALL;\ - }\ - t[NTESTS] = cpucycles();\ - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop);\ - result = (stop.tv_sec - start.tv_sec) * 1e6 + (stop.tv_nsec - start.tv_nsec) / 1e3;\ - display_result(result, t, NTESTS, MUL); - -int main(void) -{ - /* Make stdout buffer more responsive. */ - setbuf(stdout, NULL); - - spx_ctx ctx; - unsigned char pk[SPX_PK_BYTES]; - unsigned char sk[SPX_SK_BYTES]; - unsigned char *m = malloc(SPX_MLEN); - unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); - unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); - - unsigned char fors_pk[SPX_FORS_PK_BYTES]; - unsigned char fors_m[SPX_FORS_MSG_BYTES]; - unsigned char fors_sig[SPX_FORS_BYTES]; - unsigned char addr[SPX_ADDR_BYTES]; - unsigned char wots_pk[4*SPX_WOTS_PK_BYTES]; - - unsigned long long smlen; - unsigned long long mlen; - unsigned long long t[NTESTS+1]; - struct timespec start, stop; - double result; - int i; - - randombytes(m, SPX_MLEN); - randombytes(addr, SPX_ADDR_BYTES); - - printf("Parameters: n = %d, h = %d, d = %d, b = %d, k = %d, w = %d\n", - SPX_N, SPX_FULL_HEIGHT, SPX_D, SPX_FORS_HEIGHT, SPX_FORS_TREES, - SPX_WOTS_W); - - printf("Running %d iterations.\n", NTESTS); - - MEASURE("Generating keypair.. ", 1, crypto_sign_keypair(pk, sk)); - MEASURE(" - WOTS pk gen 4x.. ", (1 << SPX_TREE_HEIGHT) / 4, wots_gen_pkx4(wots_pk, &ctx, (uint32_t *) addr)); - MEASURE("Signing.. ", 1, crypto_sign(sm, &smlen, m, SPX_MLEN, sk)); - MEASURE(" - FORS signing.. ", 1, fors_sign(fors_sig, fors_pk, fors_m, &ctx, (uint32_t *) addr)); - MEASURE(" - WOTS pk gen x4.. ", SPX_D * (1 << SPX_TREE_HEIGHT) / 4, wots_gen_pkx4(wots_pk, &ctx, (uint32_t *) addr)); - MEASURE("Verifying.. ", 1, crypto_sign_open(mout, &mlen, sm, smlen, pk)); - - printf("Signature size: %d (%.2f KiB)\n", SPX_BYTES, SPX_BYTES / 1024.0); - printf("Public key size: %d (%.2f KiB)\n", SPX_PK_BYTES, SPX_PK_BYTES / 1024.0); - printf("Secret key size: %d (%.2f KiB)\n", SPX_SK_BYTES, SPX_SK_BYTES / 1024.0); - - free(m); - free(sm); - free(mout); - - return 0; -} - -static void wots_gen_pkx4(unsigned char *pk, const spx_ctx *ctx, uint32_t addr[8]) { - struct leaf_info_x4 leaf; - unsigned steps[ SPX_WOTS_LEN ] = { 0 }; - INITIALIZE_LEAF_INFO_X4(leaf, addr, steps); - wots_gen_leafx4(pk, ctx, 0, &leaf); -} diff --git a/sphincsplus/shake-avx2/test/fors.c b/sphincsplus/shake-avx2/test/fors.c deleted file mode 120000 index b2bccee..0000000 --- a/sphincsplus/shake-avx2/test/fors.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/fors.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/test/spx.c b/sphincsplus/shake-avx2/test/spx.c deleted file mode 120000 index 7af26df..0000000 --- a/sphincsplus/shake-avx2/test/spx.c +++ /dev/null @@ -1 +0,0 @@ -../../ref/test/spx.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/test/thashx4.c b/sphincsplus/shake-avx2/test/thashx4.c deleted file mode 100644 index 54e96f9..0000000 --- a/sphincsplus/shake-avx2/test/thashx4.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -#include "../thashx4.h" -#include "../thash.h" -#include "../randombytes.h" -#include "../params.h" - -int main(void) -{ - /* Make stdout buffer more responsive. */ - setbuf(stdout, NULL); - - unsigned char input[4*SPX_N]; - unsigned char output[4*SPX_N]; - unsigned char out4[4*SPX_N]; - uint32_t addr[4*8] = {0}; - unsigned int j; - spx_ctx ctx; - - randombytes(ctx.pub_seed, SPX_N); - randombytes(input, 4*SPX_N); - randombytes((unsigned char *)addr, 4 * 8 * sizeof(uint32_t)); - - printf("Testing if thash matches thashx4.. "); - - for (j = 0; j < 4; j++) { - thash(out4 + j * SPX_N, input + j * SPX_N, 1, &ctx, addr + j*8); - } - - thashx4(output + 0*SPX_N, - output + 1*SPX_N, - output + 2*SPX_N, - output + 3*SPX_N, - input + 0*SPX_N, - input + 1*SPX_N, - input + 2*SPX_N, - input + 3*SPX_N, - 1, &ctx, addr); - - if (memcmp(out4, output, 4 * SPX_N)) { - printf("failed!\n"); - return -1; - } - printf("successful.\n"); - return 0; -} diff --git a/sphincsplus/shake-avx2/thash.h b/sphincsplus/shake-avx2/thash.h deleted file mode 120000 index 937dd48..0000000 --- a/sphincsplus/shake-avx2/thash.h +++ /dev/null @@ -1 +0,0 @@ -../ref/thash.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/thash_shake_robust.c b/sphincsplus/shake-avx2/thash_shake_robust.c deleted file mode 120000 index 3be16c6..0000000 --- a/sphincsplus/shake-avx2/thash_shake_robust.c +++ /dev/null @@ -1 +0,0 @@ -../ref/thash_shake_robust.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/thash_shake_robustx4.c b/sphincsplus/shake-avx2/thash_shake_robustx4.c deleted file mode 100644 index ba136a6..0000000 --- a/sphincsplus/shake-avx2/thash_shake_robustx4.c +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include - -#include "thashx4.h" -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202x4.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4*8]) -{ - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - for (int i = 0; i < SPX_N/8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t*)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N/8+i] = _mm256_set_epi32( - addrx4[3*8+1+2*i], - addrx4[3*8+2*i], - addrx4[2*8+1+2*i], - addrx4[2*8+2*i], - addrx4[8+1+2*i], - addrx4[8+2*i], - addrx4[1+2*i], - addrx4[2*i] - ); - } - - /* SHAKE domain separator and padding */ - state[SPX_N/8+4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N/8+5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - /* We will permutate state2 with f1600x4 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is alsmost identical. */ - __m256i state2[25]; - memcpy(state2, state, 800); - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - /* By copying from state, state2 already contains the pub_seed - * and addres. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N/8) * inblocks; i++) { - state2[SPX_N/8+4+i] = _mm256_xor_si256( - state[i], - _mm256_set_epi64x( - ((int64_t*)in3)[i], - ((int64_t*)in2)[i], - ((int64_t*)in1)[i], - ((int64_t*)in0)[i] - ) - ); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[(SPX_N/8)*(1+inblocks)+4] = _mm256_xor_si256( - state2[(SPX_N/8)*(1+inblocks)+4], - _mm256_set1_epi64x(0x1f) - ); - - KeccakP1600times4_PermuteAll_24rounds(&state2[0]); - - for (int i = 0; i < SPX_N/8; i++) { - ((int64_t*)out0)[i] = _mm256_extract_epi64(state2[i], 0); - ((int64_t*)out1)[i] = _mm256_extract_epi64(state2[i], 1); - ((int64_t*)out2)[i] = _mm256_extract_epi64(state2[i], 2); - ((int64_t*)out3)[i] = _mm256_extract_epi64(state2[i], 3); - } - } else { - SPX_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, bitmask0, inblocks * SPX_N); - SPX_VLA(unsigned char, bitmask1, inblocks * SPX_N); - SPX_VLA(unsigned char, bitmask2, inblocks * SPX_N); - SPX_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf2, ctx->pub_seed, SPX_N); - memcpy(buf3, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx4 + 0*8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx4 + 1*8, SPX_ADDR_BYTES); - memcpy(buf2 + SPX_N, addrx4 + 2*8, SPX_ADDR_BYTES); - memcpy(buf3 + SPX_N, addrx4 + 3*8, SPX_ADDR_BYTES); - - shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - shake256x4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - } -} diff --git a/sphincsplus/shake-avx2/thash_shake_simple.c b/sphincsplus/shake-avx2/thash_shake_simple.c deleted file mode 120000 index 1b5a5a2..0000000 --- a/sphincsplus/shake-avx2/thash_shake_simple.c +++ /dev/null @@ -1 +0,0 @@ -../ref/thash_shake_simple.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/thash_shake_simplex4.c b/sphincsplus/shake-avx2/thash_shake_simplex4.c deleted file mode 100644 index 3763ed1..0000000 --- a/sphincsplus/shake-avx2/thash_shake_simplex4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include - -#include "thashx4.h" -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202x4.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4*8]) -{ - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - for (int i = 0; i < SPX_N/8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t*)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N/8+i] = _mm256_set_epi32( - addrx4[3*8+1+2*i], - addrx4[3*8+2*i], - addrx4[2*8+1+2*i], - addrx4[2*8+2*i], - addrx4[8+1+2*i], - addrx4[8+2*i], - addrx4[1+2*i], - addrx4[2*i] - ); - } - - for (unsigned int i = 0; i < (SPX_N/8) * inblocks; i++) { - state[SPX_N/8+4+i] = _mm256_set_epi64x( - ((int64_t*)in3)[i], - ((int64_t*)in2)[i], - ((int64_t*)in1)[i], - ((int64_t*)in0)[i] - ); - } - - /* Domain separator and padding. */ - for (int i = (SPX_N/8)*(1+inblocks)+4; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - state[(SPX_N/8)*(1+inblocks)+4] = _mm256_xor_si256( - state[(SPX_N/8)*(1+inblocks)+4], - _mm256_set1_epi64x(0x1f) - ); - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - for (int i = 0; i < SPX_N/8; i++) { - ((int64_t*)out0)[i] = _mm256_extract_epi64(state[i], 0); - ((int64_t*)out1)[i] = _mm256_extract_epi64(state[i], 1); - ((int64_t*)out2)[i] = _mm256_extract_epi64(state[i], 2); - ((int64_t*)out3)[i] = _mm256_extract_epi64(state[i], 3); - } - } else { - SPX_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - SPX_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf2, ctx->pub_seed, SPX_N); - memcpy(buf3, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx4 + 0*8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx4 + 1*8, SPX_ADDR_BYTES); - memcpy(buf2 + SPX_N, addrx4 + 2*8, SPX_ADDR_BYTES); - memcpy(buf3 + SPX_N, addrx4 + 3*8, SPX_ADDR_BYTES); - memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); - memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); - memcpy(buf2 + SPX_N + SPX_ADDR_BYTES, in2, inblocks * SPX_N); - memcpy(buf3 + SPX_N + SPX_ADDR_BYTES, in3, inblocks * SPX_N); - - shake256x4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); - } -} diff --git a/sphincsplus/shake-avx2/thashx4.h b/sphincsplus/shake-avx2/thashx4.h deleted file mode 100644 index 045237e..0000000 --- a/sphincsplus/shake-avx2/thashx4.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4*8]); - -#endif diff --git a/sphincsplus/shake-avx2/utils.c b/sphincsplus/shake-avx2/utils.c deleted file mode 120000 index e8ef6eb..0000000 --- a/sphincsplus/shake-avx2/utils.c +++ /dev/null @@ -1 +0,0 @@ -../ref/utils.c \ No newline at end of file diff --git a/sphincsplus/shake-avx2/utils.h b/sphincsplus/shake-avx2/utils.h deleted file mode 120000 index 51b0d39..0000000 --- a/sphincsplus/shake-avx2/utils.h +++ /dev/null @@ -1 +0,0 @@ -../ref/utils.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/utilsx4.c b/sphincsplus/shake-avx2/utilsx4.c deleted file mode 100644 index 4d69825..0000000 --- a/sphincsplus/shake-avx2/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utils.h" -#include "utilsx4.h" -#include "params.h" -#include "thashx4.h" -#include "address.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char* /* Where to write the leaves */, - const spx_ctx*, - uint32_t idx, void *info), - uint32_t tree_addrx4[4*8], - void *info) -{ - /* This is where we keep the intermediate nodes */ - SPX_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1 << (tree_height-2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4*SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4*idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h=0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3*SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4 - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3*SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf&3)^1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j*8, h + 1); - set_tree_index(tree_addrx4 + j*8, - (4/2) * (internal_idx&~1) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/sphincsplus/shake-avx2/utilsx4.h b/sphincsplus/shake-avx2/utilsx4.h deleted file mode 100644 index 92e0a4a..0000000 --- a/sphincsplus/shake-avx2/utilsx4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char* /* Where to write the leaves */, - const spx_ctx* /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4*8], void *info); - -#endif diff --git a/sphincsplus/shake-avx2/wots.c b/sphincsplus/shake-avx2/wots.c deleted file mode 100644 index 0788b80..0000000 --- a/sphincsplus/shake-avx2/wots.c +++ /dev/null @@ -1,271 +0,0 @@ -#include -#include - -#include "utils.h" -#include "utilsx4.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "wots.h" -#include "wotsx4.h" -#include "address.h" -#include "params.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) -{ - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8*4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs+j*8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN*SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i+j < SPX_WOTS_LEN; j++) { - idx = idxs[i+j]; - set_chain_addr(addrs+j*8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i+watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs+j*8, k + start[idxs[i+j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) -{ - int in = 0; - int out = 0; - unsigned char total; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) -{ - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) -{ - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) -{ - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j*8, leaf_idx + j ); - set_keypair_addr( pk_addr + j*8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j*8, i); - set_hash_addr(leaf_addr + j*8, 0); - set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0*wots_offset, - buffer + 1*wots_offset, - buffer + 2*wots_offset, - buffer + 3*wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k=0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index*wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) break; - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j*8, k); - } - thashx4(buffer + 0*wots_offset, - buffer + 1*wots_offset, - buffer + 2*wots_offset, - buffer + 3*wots_offset, - buffer + 0*wots_offset, - buffer + 1*wots_offset, - buffer + 2*wots_offset, - buffer + 3*wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0*SPX_N, - dest + 1*SPX_N, - dest + 2*SPX_N, - dest + 3*SPX_N, - pk_buffer + 0*wots_offset, - pk_buffer + 1*wots_offset, - pk_buffer + 2*wots_offset, - pk_buffer + 3*wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/sphincsplus/shake-avx2/wots.h b/sphincsplus/shake-avx2/wots.h deleted file mode 120000 index 8c327ea..0000000 --- a/sphincsplus/shake-avx2/wots.h +++ /dev/null @@ -1 +0,0 @@ -../ref/wots.h \ No newline at end of file diff --git a/sphincsplus/shake-avx2/wotsx4.h b/sphincsplus/shake-avx2/wotsx4.h deleted file mode 100644 index 2a311c5..0000000 --- a/sphincsplus/shake-avx2/wotsx4.h +++ /dev/null @@ -1,40 +0,0 @@ -#if !defined( WOTSX4_H_ ) -#define WOTSX4_H_ - -#include -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4*8]; - uint32_t pk_addr[4*8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - info.wots_sig = 0; \ - info.wots_sign_leaf = ~0; \ - info.wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &info.leaf_addr[8*i], addr, 32 ); \ - memcpy( &info.pk_addr[8*i], addr, 32 ); \ - } \ -} - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/sphincsplus/vectors.py b/sphincsplus/vectors.py deleted file mode 100755 index 0e0b0df..0000000 --- a/sphincsplus/vectors.py +++ /dev/null @@ -1,101 +0,0 @@ -#! /usr/bin/env python3 - -# Without arguments, generates sha256 sums of NIST KAT response files -# for each of the instances (which should match SHA256SUMS.) -# -# With two arguments, checks whether the sha256 sum of the given -# generated NIST KAT response file is correct, e.g.: -# -# ./vectors.py sphincs-shake-128s-simple shake-avx2 - -import multiprocessing -import subprocess -import itertools -import tempfile -import hashlib -import shutil -import os -import sys - -fns = ['shake', 'sha2', 'haraka'] -options = ["f", "s"] -sizes = [128, 192, 256] -thashes = ['robust', 'simple'] - -def nameFor(fn, opt, size, thash): - return f"sphincs-{fn}-{size}{opt}-{thash}" - -def make(fn, opt, size, thash, bindir, impl): - name = nameFor(fn, opt, size, thash) - overrides = [f'PARAMS=sphincs-{fn}-{size}{opt}', 'THASH='+thash] - - sys.stderr.write(f"Compiling {name} …\n") - sys.stderr.flush() - - subprocess.run(["make", "-C", impl, "clean"] + overrides, - stdout=subprocess.DEVNULL, stderr=sys.stderr, check=True) - subprocess.run(["make", '-j', "-C", impl, "PQCgenKAT_sign"] + overrides, - stdout=subprocess.DEVNULL, stderr=sys.stderr, check=True) - - shutil.move( - os.path.join(impl, 'PQCgenKAT_sign'), - os.path.join(bindir, name), - ) - - return (name, size) - -def run(name_size, bindir): - name, size = name_size - rsp = f'PQCsignKAT_{size//2}.rsp' - req = f'PQCsignKAT_{size//2}.req' - - with tempfile.TemporaryDirectory() as rundir: - sys.stderr.write(f"Running {name} …\n") - sys.stderr.flush() - - subprocess.run([os.path.join(bindir, name)], - stdout=subprocess.DEVNULL, stderr=sys.stderr, cwd=rundir, check=True) - with open(os.path.join(rundir, rsp), 'rb') as f: - h = hashlib.sha256(f.read()).hexdigest() - return f"{h} {name}" - -def generate_sums(): - with tempfile.TemporaryDirectory() as bindir: - with multiprocessing.Pool() as pool: - name_sizes = [] - for fn in fns: - for opt, size, thash in itertools.product(options, sizes, thashes): - name_sizes.append(make(fn, opt, size, thash, bindir, 'ref')) - - res = pool.starmap(run, zip(name_sizes, [bindir]*len(name_sizes))) - res.sort() - print('\n'.join(res)) - -def check_sum(name, impl): - line = None - with tempfile.TemporaryDirectory() as bindir: - for fn in fns: - for opt, size, thash in itertools.product( - options, sizes, thashes): - if nameFor(fn, opt, size, thash) != name: - continue - name_size = make(fn, opt, size, thash, bindir, impl) - line = run(name_size, bindir) - break - if not line: - sys.stderr.write("No such instance\n") - sys.exit(1) - with open('SHA256SUMS', 'r') as f: - if f.read().find(line + '\n') == -1: - sys.stderr.write(f"Test vector mismatch: {line}\n") - sys.exit(2) - sys.stderr.write("ok\n") - -if __name__ == '__main__': - if len(sys.argv) <= 1: - generate_sums() - elif len(sys.argv) == 3: - check_sum(sys.argv[1], sys.argv[2]) - else: - sys.stderr.write("Expect two or no arguments\n") - sys.exit(3) From 02965de0d27b1d074d6fb90870c3fba1f9267b90 Mon Sep 17 00:00:00 2001 From: notmike Date: Tue, 3 Feb 2026 00:15:36 -0700 Subject: [PATCH 2/7] Squashed 'sphincsplus/' content from commit 7ec789a git-subtree-dir: sphincsplus git-subtree-split: 7ec789ace6874d875f4bb84cb61b81155398167e --- .github/workflows/test-haraka-aesni.yml | 33 + .github/workflows/test-ref.yml | 37 + .github/workflows/test-sha2-avx2.yml | 33 + .github/workflows/test-shake-avx2.yml | 33 + .reuse/dep5 | 15 + LICENSE | 2 + LICENSES/0BSD.txt | 12 + LICENSES/CC0-1.0.txt | 122 ++ .../LicenseRef-SPHINCS-PLUS-Public-Domain.txt | 2 + LICENSES/MIT-0.txt | 15 + LICENSES/MIT.txt | 8 + README.md | 37 + SHA256SUMS | 36 + benchmark.py | 39 + haraka-aesni/.gitignore | 5 + haraka-aesni/Makefile | 47 + haraka-aesni/PQCgenKAT_sign.c | 1 + haraka-aesni/address.c | 1 + haraka-aesni/address.h | 1 + haraka-aesni/api.h | 1 + haraka-aesni/context.h | 16 + haraka-aesni/fors.c | 1 + haraka-aesni/fors.h | 1 + haraka-aesni/haraka.c | 720 ++++++++++++ haraka-aesni/haraka.h | 1 + haraka-aesni/haraka_offsets.h | 1 + haraka-aesni/harakax4.h | 36 + haraka-aesni/hash.h | 1 + haraka-aesni/hash_haraka.c | 1 + haraka-aesni/hash_harakax4.c | 36 + haraka-aesni/hashx4.h | 1 + haraka-aesni/merkle.c | 1 + haraka-aesni/merkle.h | 1 + haraka-aesni/params.h | 1 + .../params/params-sphincs-haraka-128f.h | 1 + .../params/params-sphincs-haraka-128s.h | 1 + .../params/params-sphincs-haraka-192f.h | 1 + .../params/params-sphincs-haraka-192s.h | 1 + .../params/params-sphincs-haraka-256f.h | 1 + .../params/params-sphincs-haraka-256s.h | 1 + haraka-aesni/randombytes.c | 1 + haraka-aesni/randombytes.h | 1 + haraka-aesni/rng.c | 1 + haraka-aesni/rng.h | 1 + haraka-aesni/sign.c | 1 + haraka-aesni/test/benchmark.c | 162 +++ haraka-aesni/test/fors.c | 1 + haraka-aesni/test/spx.c | 1 + haraka-aesni/thash.h | 1 + haraka-aesni/thash_haraka_robust.c | 1 + haraka-aesni/thash_haraka_robustx4.c | 93 ++ haraka-aesni/thash_haraka_simple.c | 1 + haraka-aesni/thash_haraka_simplex4.c | 67 ++ haraka-aesni/thashx4.h | 1 + haraka-aesni/utils.c | 1 + haraka-aesni/utils.h | 1 + haraka-aesni/utilsx4.c | 1 + haraka-aesni/utilsx4.h | 1 + haraka-aesni/wots.c | 1 + haraka-aesni/wots.h | 1 + haraka-aesni/wotsx4.h | 1 + ref/.gitignore | 5 + ref/Makefile | 65 ++ ref/PQCgenKAT_sign.c | 262 +++++ ref/address.c | 104 ++ ref/address.h | 51 + ref/api.h | 77 ++ ref/context.h | 28 + ref/fips202.c | 598 ++++++++++ ref/fips202.h | 47 + ref/fors.c | 161 +++ ref/fors.h | 32 + ref/haraka.c | 965 +++++++++++++++ ref/haraka.h | 41 + ref/haraka_offsets.h | 20 + ref/hash.h | 27 + ref/hash_haraka.c | 96 ++ ref/hash_sha2.c | 197 ++++ ref/hash_shake.c | 97 ++ ref/merkle.c | 61 + ref/merkle.h | 18 + ref/params.h | 5 + ref/params/params-sphincs-haraka-128f.h | 80 ++ ref/params/params-sphincs-haraka-128s.h | 80 ++ ref/params/params-sphincs-haraka-192f.h | 80 ++ ref/params/params-sphincs-haraka-192s.h | 80 ++ ref/params/params-sphincs-haraka-256f.h | 80 ++ ref/params/params-sphincs-haraka-256s.h | 80 ++ ref/params/params-sphincs-sha2-128f.h | 85 ++ ref/params/params-sphincs-sha2-128s.h | 85 ++ ref/params/params-sphincs-sha2-192f.h | 85 ++ ref/params/params-sphincs-sha2-192s.h | 85 ++ ref/params/params-sphincs-sha2-256f.h | 85 ++ ref/params/params-sphincs-sha2-256s.h | 85 ++ ref/params/params-sphincs-shake-128f.h | 80 ++ ref/params/params-sphincs-shake-128s.h | 80 ++ ref/params/params-sphincs-shake-192f.h | 80 ++ ref/params/params-sphincs-shake-192s.h | 80 ++ ref/params/params-sphincs-shake-256f.h | 80 ++ ref/params/params-sphincs-shake-256s.h | 80 ++ ref/randombytes.c | 43 + ref/randombytes.h | 6 + ref/rng.c | 218 ++++ ref/rng.h | 54 + ref/sha2.c | 700 +++++++++++ ref/sha2.h | 43 + ref/sha2_offsets.h | 20 + ref/shake_offsets.h | 20 + ref/sign.c | 287 +++++ ref/test/benchmark.c | 173 +++ ref/test/cycles.c | 110 ++ ref/test/cycles.h | 7 + ref/test/fors.c | 41 + ref/test/haraka.c | 155 +++ ref/test/spx.c | 125 ++ ref/thash.h | 13 + ref/thash_haraka_robust.c | 46 + ref/thash_haraka_simple.c | 37 + ref/thash_sha2_robust.c | 74 ++ ref/thash_sha2_simple.c | 59 + ref/thash_shake_robust.c | 31 + ref/thash_shake_simple.c | 24 + ref/utils.c | 154 +++ ref/utils.h | 64 + ref/utilsx1.c | 100 ++ ref/utilsx1.h | 26 + ref/wots.c | 112 ++ ref/wots.h | 25 + ref/wotsx1.c | 73 ++ ref/wotsx1.h | 36 + sha2-avx2/.gitignore | 6 + sha2-avx2/Makefile | 48 + sha2-avx2/PQCgenKAT_sign.c | 1 + sha2-avx2/address.c | 1 + sha2-avx2/address.h | 1 + sha2-avx2/api.h | 1 + sha2-avx2/context.h | 18 + sha2-avx2/fors.c | 233 ++++ sha2-avx2/fors.h | 1 + sha2-avx2/hash.h | 1 + sha2-avx2/hash_sha2.c | 1 + sha2-avx2/hash_sha2x8.c | 74 ++ sha2-avx2/hashx8.h | 19 + sha2-avx2/merkle.c | 67 ++ sha2-avx2/merkle.h | 1 + sha2-avx2/params.h | 1 + sha2-avx2/params/params-sphincs-sha2-128f.h | 1 + sha2-avx2/params/params-sphincs-sha2-128s.h | 1 + sha2-avx2/params/params-sphincs-sha2-192f.h | 1 + sha2-avx2/params/params-sphincs-sha2-192s.h | 1 + sha2-avx2/params/params-sphincs-sha2-256f.h | 1 + sha2-avx2/params/params-sphincs-sha2-256s.h | 1 + sha2-avx2/randombytes.c | 1 + sha2-avx2/randombytes.h | 1 + sha2-avx2/rng.c | 1 + sha2-avx2/rng.h | 1 + sha2-avx2/sha2.c | 1 + sha2-avx2/sha2.h | 1 + sha2-avx2/sha256avx.c | 294 +++++ sha2-avx2/sha256avx.h | 96 ++ sha2-avx2/sha256x8.c | 201 ++++ sha2-avx2/sha256x8.h | 69 ++ sha2-avx2/sha2_offsets.h | 1 + sha2-avx2/sha512x4.c | 462 ++++++++ sha2-avx2/sha512x4.h | 44 + sha2-avx2/sign.c | 1 + sha2-avx2/test/benchmark.c | 162 +++ sha2-avx2/test/fors.c | 1 + sha2-avx2/test/spx.c | 1 + sha2-avx2/test/thashx8.c | 94 ++ sha2-avx2/thash.h | 1 + sha2-avx2/thash_sha2_robust.c | 1 + sha2-avx2/thash_sha2_robustx8.c | 276 +++++ sha2-avx2/thash_sha2_simple.c | 1 + sha2-avx2/thash_sha2_simplex8.c | 220 ++++ sha2-avx2/thashx8.h | 27 + sha2-avx2/utils.c | 1 + sha2-avx2/utils.h | 1 + sha2-avx2/utilsx8.c | 146 +++ sha2-avx2/utilsx8.h | 28 + sha2-avx2/wots.c | 293 +++++ sha2-avx2/wots.h | 1 + sha2-avx2/wotsx8.h | 40 + shake-a64/.gitignore | 5 + shake-a64/Makefile | 49 + shake-a64/PQCgenKAT_sign.c | 1 + shake-a64/address.c | 1 + shake-a64/address.h | 1 + shake-a64/api.h | 1 + shake-a64/context.h | 13 + shake-a64/f1600x2.h | 11 + shake-a64/f1600x2.s | 143 +++ shake-a64/f1600x2_const.c | 30 + shake-a64/fips202.c | 1 + shake-a64/fips202.h | 1 + shake-a64/fips202x2.c | 165 +++ shake-a64/fips202x2.h | 24 + shake-a64/fors.c | 198 ++++ shake-a64/fors.h | 1 + shake-a64/hash.h | 1 + shake-a64/hash_shake.c | 1 + shake-a64/hash_shakex2.c | 51 + shake-a64/hashx2.h | 14 + shake-a64/merkle.c | 65 ++ shake-a64/merkle.h | 1 + shake-a64/params.h | 1 + shake-a64/params/params-sphincs-shake-128f.h | 1 + shake-a64/params/params-sphincs-shake-128s.h | 1 + shake-a64/params/params-sphincs-shake-192f.h | 1 + shake-a64/params/params-sphincs-shake-192s.h | 1 + shake-a64/params/params-sphincs-shake-256f.h | 1 + shake-a64/params/params-sphincs-shake-256s.h | 1 + shake-a64/randombytes.c | 1 + shake-a64/randombytes.h | 1 + shake-a64/rng.c | 1 + shake-a64/rng.h | 1 + shake-a64/shake_offsets.h | 1 + shake-a64/sign.c | 1 + shake-a64/test/benchmark.c | 175 +++ shake-a64/test/cycles.c | 1 + shake-a64/test/cycles.h | 1 + shake-a64/test/fors.c | 1 + shake-a64/test/spx.c | 1 + shake-a64/test/thashx2.c | 43 + shake-a64/thash.h | 12 + shake-a64/thash_shake_robustx2.c | 112 ++ shake-a64/thash_shake_simplex2.c | 83 ++ shake-a64/thashx2.h | 16 + shake-a64/utils.c | 1 + shake-a64/utils.h | 1 + shake-a64/utilsx2.c | 130 +++ shake-a64/utilsx2.h | 28 + shake-a64/wots.c | 261 +++++ shake-a64/wots.h | 1 + shake-a64/wotsx2.h | 40 + shake-avx2/.gitignore | 6 + shake-avx2/Makefile | 56 + shake-avx2/PQCgenKAT_sign.c | 1 + shake-avx2/address.c | 1 + shake-avx2/address.h | 1 + shake-avx2/api.h | 1 + shake-avx2/context.h | 13 + shake-avx2/fips202.c | 1 + shake-avx2/fips202.h | 1 + shake-avx2/fips202x4.c | 225 ++++ shake-avx2/fips202x4.h | 24 + shake-avx2/fors.c | 209 ++++ shake-avx2/fors.h | 1 + shake-avx2/hash.h | 1 + shake-avx2/hash_shake.c | 1 + shake-avx2/hash_shakex4.c | 63 + shake-avx2/hashx4.h | 16 + .../keccak4x/KeccakP-1600-times4-SIMD256.c | 1030 +++++++++++++++++ shake-avx2/keccak4x/KeccakP-1600-times4-SnP.h | 50 + .../keccak4x/KeccakP-1600-unrolling.macros | 198 ++++ shake-avx2/keccak4x/SIMD256-config.h | 3 + shake-avx2/keccak4x/align.h | 34 + shake-avx2/keccak4x/brg_endian.h | 142 +++ shake-avx2/merkle.c | 65 ++ shake-avx2/merkle.h | 1 + shake-avx2/params.h | 1 + shake-avx2/params/params-sphincs-shake-128f.h | 1 + shake-avx2/params/params-sphincs-shake-128s.h | 1 + shake-avx2/params/params-sphincs-shake-192f.h | 1 + shake-avx2/params/params-sphincs-shake-192s.h | 1 + shake-avx2/params/params-sphincs-shake-256f.h | 1 + shake-avx2/params/params-sphincs-shake-256s.h | 1 + shake-avx2/randombytes.c | 1 + shake-avx2/randombytes.h | 1 + shake-avx2/rng.c | 1 + shake-avx2/rng.h | 1 + shake-avx2/shake_offsets.h | 1 + shake-avx2/sign.c | 1 + shake-avx2/test/benchmark.c | 161 +++ shake-avx2/test/fors.c | 1 + shake-avx2/test/spx.c | 1 + shake-avx2/test/thashx4.c | 47 + shake-avx2/thash.h | 1 + shake-avx2/thash_shake_robust.c | 1 + shake-avx2/thash_shake_robustx4.c | 131 +++ shake-avx2/thash_shake_simple.c | 1 + shake-avx2/thash_shake_simplex4.c | 98 ++ shake-avx2/thashx4.h | 19 + shake-avx2/utils.c | 1 + shake-avx2/utils.h | 1 + shake-avx2/utilsx4.c | 138 +++ shake-avx2/utilsx4.h | 28 + shake-avx2/wots.c | 271 +++++ shake-avx2/wots.h | 1 + shake-avx2/wotsx4.h | 40 + vectors.py | 101 ++ 291 files changed, 16792 insertions(+) create mode 100644 .github/workflows/test-haraka-aesni.yml create mode 100644 .github/workflows/test-ref.yml create mode 100644 .github/workflows/test-sha2-avx2.yml create mode 100644 .github/workflows/test-shake-avx2.yml create mode 100644 .reuse/dep5 create mode 100644 LICENSE create mode 100644 LICENSES/0BSD.txt create mode 100644 LICENSES/CC0-1.0.txt create mode 100644 LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt create mode 100644 LICENSES/MIT-0.txt create mode 100644 LICENSES/MIT.txt create mode 100644 README.md create mode 100644 SHA256SUMS create mode 100755 benchmark.py create mode 100644 haraka-aesni/.gitignore create mode 100644 haraka-aesni/Makefile create mode 120000 haraka-aesni/PQCgenKAT_sign.c create mode 120000 haraka-aesni/address.c create mode 120000 haraka-aesni/address.h create mode 120000 haraka-aesni/api.h create mode 100644 haraka-aesni/context.h create mode 120000 haraka-aesni/fors.c create mode 120000 haraka-aesni/fors.h create mode 100644 haraka-aesni/haraka.c create mode 120000 haraka-aesni/haraka.h create mode 120000 haraka-aesni/haraka_offsets.h create mode 100644 haraka-aesni/harakax4.h create mode 120000 haraka-aesni/hash.h create mode 120000 haraka-aesni/hash_haraka.c create mode 100644 haraka-aesni/hash_harakax4.c create mode 120000 haraka-aesni/hashx4.h create mode 120000 haraka-aesni/merkle.c create mode 120000 haraka-aesni/merkle.h create mode 120000 haraka-aesni/params.h create mode 120000 haraka-aesni/params/params-sphincs-haraka-128f.h create mode 120000 haraka-aesni/params/params-sphincs-haraka-128s.h create mode 120000 haraka-aesni/params/params-sphincs-haraka-192f.h create mode 120000 haraka-aesni/params/params-sphincs-haraka-192s.h create mode 120000 haraka-aesni/params/params-sphincs-haraka-256f.h create mode 120000 haraka-aesni/params/params-sphincs-haraka-256s.h create mode 120000 haraka-aesni/randombytes.c create mode 120000 haraka-aesni/randombytes.h create mode 120000 haraka-aesni/rng.c create mode 120000 haraka-aesni/rng.h create mode 120000 haraka-aesni/sign.c create mode 100644 haraka-aesni/test/benchmark.c create mode 120000 haraka-aesni/test/fors.c create mode 120000 haraka-aesni/test/spx.c create mode 120000 haraka-aesni/thash.h create mode 120000 haraka-aesni/thash_haraka_robust.c create mode 100644 haraka-aesni/thash_haraka_robustx4.c create mode 120000 haraka-aesni/thash_haraka_simple.c create mode 100644 haraka-aesni/thash_haraka_simplex4.c create mode 120000 haraka-aesni/thashx4.h create mode 120000 haraka-aesni/utils.c create mode 120000 haraka-aesni/utils.h create mode 120000 haraka-aesni/utilsx4.c create mode 120000 haraka-aesni/utilsx4.h create mode 120000 haraka-aesni/wots.c create mode 120000 haraka-aesni/wots.h create mode 120000 haraka-aesni/wotsx4.h create mode 100644 ref/.gitignore create mode 100644 ref/Makefile create mode 100644 ref/PQCgenKAT_sign.c create mode 100644 ref/address.c create mode 100644 ref/address.h create mode 100644 ref/api.h create mode 100644 ref/context.h create mode 100644 ref/fips202.c create mode 100644 ref/fips202.h create mode 100644 ref/fors.c create mode 100644 ref/fors.h create mode 100644 ref/haraka.c create mode 100644 ref/haraka.h create mode 100644 ref/haraka_offsets.h create mode 100644 ref/hash.h create mode 100644 ref/hash_haraka.c create mode 100644 ref/hash_sha2.c create mode 100644 ref/hash_shake.c create mode 100644 ref/merkle.c create mode 100644 ref/merkle.h create mode 100644 ref/params.h create mode 100644 ref/params/params-sphincs-haraka-128f.h create mode 100644 ref/params/params-sphincs-haraka-128s.h create mode 100644 ref/params/params-sphincs-haraka-192f.h create mode 100644 ref/params/params-sphincs-haraka-192s.h create mode 100644 ref/params/params-sphincs-haraka-256f.h create mode 100644 ref/params/params-sphincs-haraka-256s.h create mode 100644 ref/params/params-sphincs-sha2-128f.h create mode 100644 ref/params/params-sphincs-sha2-128s.h create mode 100644 ref/params/params-sphincs-sha2-192f.h create mode 100644 ref/params/params-sphincs-sha2-192s.h create mode 100644 ref/params/params-sphincs-sha2-256f.h create mode 100644 ref/params/params-sphincs-sha2-256s.h create mode 100644 ref/params/params-sphincs-shake-128f.h create mode 100644 ref/params/params-sphincs-shake-128s.h create mode 100644 ref/params/params-sphincs-shake-192f.h create mode 100644 ref/params/params-sphincs-shake-192s.h create mode 100644 ref/params/params-sphincs-shake-256f.h create mode 100644 ref/params/params-sphincs-shake-256s.h create mode 100644 ref/randombytes.c create mode 100644 ref/randombytes.h create mode 100644 ref/rng.c create mode 100644 ref/rng.h create mode 100644 ref/sha2.c create mode 100644 ref/sha2.h create mode 100644 ref/sha2_offsets.h create mode 100644 ref/shake_offsets.h create mode 100644 ref/sign.c create mode 100644 ref/test/benchmark.c create mode 100644 ref/test/cycles.c create mode 100644 ref/test/cycles.h create mode 100644 ref/test/fors.c create mode 100644 ref/test/haraka.c create mode 100644 ref/test/spx.c create mode 100644 ref/thash.h create mode 100644 ref/thash_haraka_robust.c create mode 100644 ref/thash_haraka_simple.c create mode 100644 ref/thash_sha2_robust.c create mode 100644 ref/thash_sha2_simple.c create mode 100644 ref/thash_shake_robust.c create mode 100644 ref/thash_shake_simple.c create mode 100644 ref/utils.c create mode 100644 ref/utils.h create mode 100644 ref/utilsx1.c create mode 100644 ref/utilsx1.h create mode 100644 ref/wots.c create mode 100644 ref/wots.h create mode 100644 ref/wotsx1.c create mode 100644 ref/wotsx1.h create mode 100644 sha2-avx2/.gitignore create mode 100644 sha2-avx2/Makefile create mode 120000 sha2-avx2/PQCgenKAT_sign.c create mode 120000 sha2-avx2/address.c create mode 120000 sha2-avx2/address.h create mode 120000 sha2-avx2/api.h create mode 100644 sha2-avx2/context.h create mode 100644 sha2-avx2/fors.c create mode 120000 sha2-avx2/fors.h create mode 120000 sha2-avx2/hash.h create mode 120000 sha2-avx2/hash_sha2.c create mode 100644 sha2-avx2/hash_sha2x8.c create mode 100644 sha2-avx2/hashx8.h create mode 100644 sha2-avx2/merkle.c create mode 120000 sha2-avx2/merkle.h create mode 120000 sha2-avx2/params.h create mode 120000 sha2-avx2/params/params-sphincs-sha2-128f.h create mode 120000 sha2-avx2/params/params-sphincs-sha2-128s.h create mode 120000 sha2-avx2/params/params-sphincs-sha2-192f.h create mode 120000 sha2-avx2/params/params-sphincs-sha2-192s.h create mode 120000 sha2-avx2/params/params-sphincs-sha2-256f.h create mode 120000 sha2-avx2/params/params-sphincs-sha2-256s.h create mode 120000 sha2-avx2/randombytes.c create mode 120000 sha2-avx2/randombytes.h create mode 120000 sha2-avx2/rng.c create mode 120000 sha2-avx2/rng.h create mode 120000 sha2-avx2/sha2.c create mode 120000 sha2-avx2/sha2.h create mode 100644 sha2-avx2/sha256avx.c create mode 100644 sha2-avx2/sha256avx.h create mode 100644 sha2-avx2/sha256x8.c create mode 100644 sha2-avx2/sha256x8.h create mode 120000 sha2-avx2/sha2_offsets.h create mode 100644 sha2-avx2/sha512x4.c create mode 100644 sha2-avx2/sha512x4.h create mode 120000 sha2-avx2/sign.c create mode 100644 sha2-avx2/test/benchmark.c create mode 120000 sha2-avx2/test/fors.c create mode 120000 sha2-avx2/test/spx.c create mode 100644 sha2-avx2/test/thashx8.c create mode 120000 sha2-avx2/thash.h create mode 120000 sha2-avx2/thash_sha2_robust.c create mode 100644 sha2-avx2/thash_sha2_robustx8.c create mode 120000 sha2-avx2/thash_sha2_simple.c create mode 100644 sha2-avx2/thash_sha2_simplex8.c create mode 100644 sha2-avx2/thashx8.h create mode 120000 sha2-avx2/utils.c create mode 120000 sha2-avx2/utils.h create mode 100644 sha2-avx2/utilsx8.c create mode 100644 sha2-avx2/utilsx8.h create mode 100644 sha2-avx2/wots.c create mode 120000 sha2-avx2/wots.h create mode 100644 sha2-avx2/wotsx8.h create mode 100644 shake-a64/.gitignore create mode 100644 shake-a64/Makefile create mode 120000 shake-a64/PQCgenKAT_sign.c create mode 120000 shake-a64/address.c create mode 120000 shake-a64/address.h create mode 120000 shake-a64/api.h create mode 100644 shake-a64/context.h create mode 100644 shake-a64/f1600x2.h create mode 100644 shake-a64/f1600x2.s create mode 100644 shake-a64/f1600x2_const.c create mode 120000 shake-a64/fips202.c create mode 120000 shake-a64/fips202.h create mode 100644 shake-a64/fips202x2.c create mode 100644 shake-a64/fips202x2.h create mode 100644 shake-a64/fors.c create mode 120000 shake-a64/fors.h create mode 120000 shake-a64/hash.h create mode 120000 shake-a64/hash_shake.c create mode 100644 shake-a64/hash_shakex2.c create mode 100644 shake-a64/hashx2.h create mode 100644 shake-a64/merkle.c create mode 120000 shake-a64/merkle.h create mode 120000 shake-a64/params.h create mode 120000 shake-a64/params/params-sphincs-shake-128f.h create mode 120000 shake-a64/params/params-sphincs-shake-128s.h create mode 120000 shake-a64/params/params-sphincs-shake-192f.h create mode 120000 shake-a64/params/params-sphincs-shake-192s.h create mode 120000 shake-a64/params/params-sphincs-shake-256f.h create mode 120000 shake-a64/params/params-sphincs-shake-256s.h create mode 120000 shake-a64/randombytes.c create mode 120000 shake-a64/randombytes.h create mode 120000 shake-a64/rng.c create mode 120000 shake-a64/rng.h create mode 120000 shake-a64/shake_offsets.h create mode 120000 shake-a64/sign.c create mode 100644 shake-a64/test/benchmark.c create mode 120000 shake-a64/test/cycles.c create mode 120000 shake-a64/test/cycles.h create mode 120000 shake-a64/test/fors.c create mode 120000 shake-a64/test/spx.c create mode 100644 shake-a64/test/thashx2.c create mode 100644 shake-a64/thash.h create mode 100644 shake-a64/thash_shake_robustx2.c create mode 100644 shake-a64/thash_shake_simplex2.c create mode 100644 shake-a64/thashx2.h create mode 120000 shake-a64/utils.c create mode 120000 shake-a64/utils.h create mode 100644 shake-a64/utilsx2.c create mode 100644 shake-a64/utilsx2.h create mode 100644 shake-a64/wots.c create mode 120000 shake-a64/wots.h create mode 100644 shake-a64/wotsx2.h create mode 100644 shake-avx2/.gitignore create mode 100644 shake-avx2/Makefile create mode 120000 shake-avx2/PQCgenKAT_sign.c create mode 120000 shake-avx2/address.c create mode 120000 shake-avx2/address.h create mode 120000 shake-avx2/api.h create mode 100644 shake-avx2/context.h create mode 120000 shake-avx2/fips202.c create mode 120000 shake-avx2/fips202.h create mode 100644 shake-avx2/fips202x4.c create mode 100644 shake-avx2/fips202x4.h create mode 100644 shake-avx2/fors.c create mode 120000 shake-avx2/fors.h create mode 120000 shake-avx2/hash.h create mode 120000 shake-avx2/hash_shake.c create mode 100644 shake-avx2/hash_shakex4.c create mode 100644 shake-avx2/hashx4.h create mode 100644 shake-avx2/keccak4x/KeccakP-1600-times4-SIMD256.c create mode 100644 shake-avx2/keccak4x/KeccakP-1600-times4-SnP.h create mode 100644 shake-avx2/keccak4x/KeccakP-1600-unrolling.macros create mode 100644 shake-avx2/keccak4x/SIMD256-config.h create mode 100644 shake-avx2/keccak4x/align.h create mode 100644 shake-avx2/keccak4x/brg_endian.h create mode 100644 shake-avx2/merkle.c create mode 120000 shake-avx2/merkle.h create mode 120000 shake-avx2/params.h create mode 120000 shake-avx2/params/params-sphincs-shake-128f.h create mode 120000 shake-avx2/params/params-sphincs-shake-128s.h create mode 120000 shake-avx2/params/params-sphincs-shake-192f.h create mode 120000 shake-avx2/params/params-sphincs-shake-192s.h create mode 120000 shake-avx2/params/params-sphincs-shake-256f.h create mode 120000 shake-avx2/params/params-sphincs-shake-256s.h create mode 120000 shake-avx2/randombytes.c create mode 120000 shake-avx2/randombytes.h create mode 120000 shake-avx2/rng.c create mode 120000 shake-avx2/rng.h create mode 120000 shake-avx2/shake_offsets.h create mode 120000 shake-avx2/sign.c create mode 100644 shake-avx2/test/benchmark.c create mode 120000 shake-avx2/test/fors.c create mode 120000 shake-avx2/test/spx.c create mode 100644 shake-avx2/test/thashx4.c create mode 120000 shake-avx2/thash.h create mode 120000 shake-avx2/thash_shake_robust.c create mode 100644 shake-avx2/thash_shake_robustx4.c create mode 120000 shake-avx2/thash_shake_simple.c create mode 100644 shake-avx2/thash_shake_simplex4.c create mode 100644 shake-avx2/thashx4.h create mode 120000 shake-avx2/utils.c create mode 120000 shake-avx2/utils.h create mode 100644 shake-avx2/utilsx4.c create mode 100644 shake-avx2/utilsx4.h create mode 100644 shake-avx2/wots.c create mode 120000 shake-avx2/wots.h create mode 100644 shake-avx2/wotsx4.h create mode 100755 vectors.py diff --git a/.github/workflows/test-haraka-aesni.yml b/.github/workflows/test-haraka-aesni.yml new file mode 100644 index 0000000..4f0e713 --- /dev/null +++ b/.github/workflows/test-haraka-aesni.yml @@ -0,0 +1,33 @@ +name: Tests for haraka-aesni implementation + +on: + - push + - pull_request + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + size: + - 128 + - 192 + - 256 + option: + - s + - f + thash: + - simple + - robust + steps: + - uses: actions/checkout@v1 + - name: Run make + run: | + make -C haraka-aesni THASH=${{ matrix.thash }} clean + make -C haraka-aesni THASH=${{ matrix.thash }} PARAMS=sphincs-haraka-${{ matrix.size }}${{ matrix.option }} tests + make -C haraka-aesni THASH=${{ matrix.thash }} PARAMS=sphincs-haraka-${{ matrix.size }}${{ matrix.option }} test + make -C haraka-aesni THASH=${{ matrix.thash }} PARAMS=sphincs-haraka-${{ matrix.size }}${{ matrix.option }} PQCgenKAT_sign + - name: Run PQCgenKAT_sign + run: python3 vectors.py sphincs-haraka-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} haraka-aesni + +# vim: set ft=yaml ts=2 sw=2 et : diff --git a/.github/workflows/test-ref.yml b/.github/workflows/test-ref.yml new file mode 100644 index 0000000..b97ded2 --- /dev/null +++ b/.github/workflows/test-ref.yml @@ -0,0 +1,37 @@ +name: Tests for ref implementation + +on: + - push + - pull_request + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + hash: + - sha2 + - shake + - haraka + size: + - 128 + - 192 + - 256 + option: + - s + - f + thash: + - simple + - robust + steps: + - uses: actions/checkout@v1 + - name: Run make + run: | + make -C ref HASH=${{ matrix.hash }} THASH=${{ matrix.thash }} clean + make -C ref HASH=${{ matrix.hash }} THASH=${{ matrix.thash }} PARAMS=sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }} tests + make -C ref HASH=${{ matrix.hash }} THASH=${{ matrix.thash }} PARAMS=sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }} test + make -C ref THASH=${{ matrix.thash }} PQCgenKAT_sign + - name: Run PQCgenKAT_sign + run: python3 vectors.py sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} ref + +# vim: set ft=yaml ts=2 sw=2 et : diff --git a/.github/workflows/test-sha2-avx2.yml b/.github/workflows/test-sha2-avx2.yml new file mode 100644 index 0000000..d0dd58e --- /dev/null +++ b/.github/workflows/test-sha2-avx2.yml @@ -0,0 +1,33 @@ +name: Tests for sha2-avx2 implementation + +on: + - push + - pull_request + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + size: + - 128 + - 192 + - 256 + option: + - s + - f + thash: + - simple + - robust + steps: + - uses: actions/checkout@v1 + - name: Run make + run: | + make -C sha2-avx2 THASH=${{ matrix.thash }} clean + make -C sha2-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-sha2-${{ matrix.size }}${{ matrix.option }} tests + make -C sha2-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-sha2-${{ matrix.size }}${{ matrix.option }} test + make -C sha2-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-sha2-${{ matrix.size }}${{ matrix.option }} PQCgenKAT_sign + - name: Run PQCgenKAT_sign + run: python3 vectors.py sphincs-sha2-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} sha2-avx2 + +# vim: set ft=yaml ts=2 sw=2 et : diff --git a/.github/workflows/test-shake-avx2.yml b/.github/workflows/test-shake-avx2.yml new file mode 100644 index 0000000..4e6ddea --- /dev/null +++ b/.github/workflows/test-shake-avx2.yml @@ -0,0 +1,33 @@ +name: Tests for shake-avx2 implementation + +on: + - push + - pull_request + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + size: + - 128 + - 192 + - 256 + option: + - s + - f + thash: + - simple + - robust + steps: + - uses: actions/checkout@v1 + - name: Run make + run: | + make -C shake-avx2 THASH=${{ matrix.thash }} clean + make -C shake-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-shake-${{ matrix.size }}${{ matrix.option }} tests + make -C shake-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-shake-${{ matrix.size }}${{ matrix.option }} test + make -C shake-avx2 THASH=${{ matrix.thash }} PARAMS=sphincs-shake-${{ matrix.size }}${{ matrix.option }} PQCgenKAT_sign + - name: Run PQCgenKAT_sign + run: python3 vectors.py sphincs-shake-${{ matrix.size }}${{ matrix.option }}-${{ matrix.thash }} shake-avx2 + +# vim: set ft=yaml ts=2 sw=2 et : diff --git a/.reuse/dep5 b/.reuse/dep5 new file mode 100644 index 0000000..8d2def9 --- /dev/null +++ b/.reuse/dep5 @@ -0,0 +1,15 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: SPHINCS+ +Upstream-Contact: contact@sphincs.org +Souce: https://github.com/sphincs/sphincsplus + +Files: * +License: LicenseRef-SPHINCS-PLUS-Public-Domain OR CC0-1.0 OR 0BSD OR MIT-0 + +Files: ref/haraka.c +Copyright: 2016 Thomas Pornin and SPHINCS+ team +License: (LicenseRef-SPHINCS-PLUS-Public-Domain OR CC0-1.0 OR 0BSD OR MIT-0) AND MIT + +Files: ref/PQCgenKAT_sign.c ref/rng.c ref/rng.h +Copyright: 2017 Bassham, Lawrence E (Fed). +License: All rights reserved. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ca88ec4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,2 @@ +SPDX-License-Identifier: (LicenseRef-SPHINCS-PLUS-Public-Domain OR CC0-1.0 OR 0BSD OR MIT-0) AND MIT + diff --git a/LICENSES/0BSD.txt b/LICENSES/0BSD.txt new file mode 100644 index 0000000..c19ef1c --- /dev/null +++ b/LICENSES/0BSD.txt @@ -0,0 +1,12 @@ +BSD Zero Clause License + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE +FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/LICENSES/CC0-1.0.txt b/LICENSES/CC0-1.0.txt new file mode 100644 index 0000000..6ca207e --- /dev/null +++ b/LICENSES/CC0-1.0.txt @@ -0,0 +1,122 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. + diff --git a/LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt b/LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt new file mode 100644 index 0000000..8c93d5a --- /dev/null +++ b/LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt @@ -0,0 +1,2 @@ +This work is hereby placed into the public domain. + diff --git a/LICENSES/MIT-0.txt b/LICENSES/MIT-0.txt new file mode 100644 index 0000000..11f9808 --- /dev/null +++ b/LICENSES/MIT-0.txt @@ -0,0 +1,15 @@ +MIT No Attribution + +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. + +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. + diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 0000000..66cb02b --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,8 @@ +MIT License + +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 (including the next paragraph) 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. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..5948b7d --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +## SPHINCS+ + +This repository contains the software that accompanies the [SPHINCS+ submission](https://sphincs.org/) to [NIST's Post-Quantum Cryptography](https://csrc.nist.gov/Projects/Post-Quantum-Cryptography) project. + +![][test-ref] +![][test-sha256-avx2] +![][test-shake256-avx2] +![][test-haraka-aesni] + +### Parameters + +The [SPHINCS+ specification](https://sphincs.org/data/sphincs+-specification.pdf) proposed a set of 36 named instances, specifying hash functions and concrete parameters for the security level, tree dimensions, WOTS+ and FORS. This reference implementation allows for more flexibility, as parameters can be specified in a `params.h` file. The proposed parameter sets have been predefined in `ref/params/params-*.h`, and the hash function can be varied by linking with the different implementations of `hash.h`, i.e., `hash_haraka.c`, `hash_sha2.c` and `hash_shake.c`, as well as different implementations of `thash.h`, i.e., `*_robust.c` and `*_simple.c`. This is demonstrated in the `Makefile`. See the table below for a summary of the parameter sets. These parameters target the NIST security categories 1, 3 and 5; for each category, there is a parameter set geared towards either small signatures or fast signature generation. + +| | n | h | d | log(t) | k | w | bit security | pk bytes | sk bytes | sig bytes | +| :------------ | -: | -: | -: | -----: | -: | --: | -----------: | -------: | -------: | --------: | +| SPHINCS+-128s | 16 | 63 | 7 | 12 | 14 | 16 | 133 | 32 | 64 | 7,856 | +| SPHINCS+-128f | 16 | 66 | 22 | 6 | 33 | 16 | 128 | 32 | 64 | 17,088 | +| SPHINCS+-192s | 24 | 63 | 7 | 14 | 17 | 16 | 193 | 48 | 96 | 16,224 | +| SPHINCS+-192f | 24 | 66 | 22 | 8 | 33 | 16 | 194 | 48 | 96 | 35,664 | +| SPHINCS+-256s | 32 | 64 | 8 | 14 | 22 | 16 | 255 | 64 | 128 | 29,792 | +| SPHINCS+-256f | 32 | 68 | 17 | 9 | 35 | 16 | 255 | 64 | 128 | 49,856 | + +### License + +All included code has been placed into +[Public Domain](LICENSES/LicenseRef-SPHINCS-PLUS-Public-Domain.txt) +and is available under various open source licenses +([Creative Commons Zero v1.0 Universal (CC0-1.0)](LICENSES/CC0-1.0.txt), +[BSD Zero Clause License (0BSD)](LICENSES/0BSD.txt), and +[MIT No Attribution (MIT-0)](LICENSES/MIT-0.txt), +see the [LICENSE file](LICENSE) and the licenses in the [LICENSES folder](LICENSES)), with the exception of `rng.c`, `rng.h` and `PQCgenKAT_sign.c`, which were provided by NIST, and parts of `ref/haraka.c`, which are under +[MIT license (MIT)](LICENSES/MIT.txt). + +[test-ref]: https://github.com/sphincs/sphincsplus/actions/workflows/test-ref.yml/badge.svg +[test-sha256-avx2]: https://github.com/sphincs/sphincsplus/actions/workflows/test-sha256-avx2.yml/badge.svg +[test-shake256-avx2]: https://github.com/sphincs/sphincsplus/actions/workflows/test-shake256-avx2.yml/badge.svg +[test-haraka-aesni]: https://github.com/sphincs/sphincsplus/actions/workflows/test-haraka-aesni.yml/badge.svg diff --git a/SHA256SUMS b/SHA256SUMS new file mode 100644 index 0000000..e781c99 --- /dev/null +++ b/SHA256SUMS @@ -0,0 +1,36 @@ +9e1b3168520c917b6de676caa7a5799ec972e55caa150090e8452c80c299545e sphincs-haraka-128f-robust +c6a28dcf0667bd91c7bb46814ac7408c0375727fe5fec7d41332149006d3f9d7 sphincs-haraka-128f-simple +f93f4a554322080545a70f85ce936a12acc2fe928a243e3d13546ffe87872a9e sphincs-haraka-128s-robust +3c9b181d3d96c066039b77e9accd926745fe1ecb010039d3579140b877da6f33 sphincs-haraka-128s-simple +8876bfae8924983db27acfeaee6252d37cea86f05fcc4b16ea2c902d717e6a6e sphincs-haraka-192f-robust +df26bd02796f5ad9d6ff412793960e79ec911cbf4521656814895e6ef5a1db83 sphincs-haraka-192f-simple +6cfde6cb5f9ce93eb3f7b0845e1149f661f92000f54e9d340c0bff504920ec7e sphincs-haraka-192s-robust +64037177e1524f2b2d3ea4a79fdaf9352eb39a3aa6e68bc9d3316b7c2b835820 sphincs-haraka-192s-simple +a838509fa6ec49ade2638efc35d9e29fdb56bd9b843d5e1f48210a2cab218332 sphincs-haraka-256f-robust +e1e3258be6b4467bcea81392363f657a58278a5b99fe240f29e388b0fe72f5da sphincs-haraka-256f-simple +b5c5cc535f03789c25c018c009615ac62ba5b64188e4db5e3ede5513e3704dcc sphincs-haraka-256s-robust +9428a566a2c2ee03665fc0eb2dbf208deb1b28716dc8c2d5e7c036a9f83d31da sphincs-haraka-256s-simple +b6c82007bbce794f9fd67de708cd4d959319c744b918ddb28795fd491b713aa9 sphincs-sha2-128f-robust +708f6ab77f8026361e975f7be7b9b5d1cd8aca56e4a3604c85ef3f9fe6618549 sphincs-sha2-128f-simple +f4c2f31082fc8ad15419edc4f24c34a83d909f75eb37ea5ffe53df0fb5ef5306 sphincs-sha2-128s-robust +65942fac8e225fde77dd277d297e68c94c2e25a2a4089f88be4b56fa92b18a84 sphincs-sha2-128s-simple +b8e617db2099e617dfc372ff732eead88872aea791e2fe82628568d75dd03c78 sphincs-sha2-192f-robust +84b1a342683bcad658efb6c65f7367c6b30623e74e3a24c2238d19eaf74722ab sphincs-sha2-192f-simple +50c4b94dc788446077b48af1d8fa0170dc2114b4cb72a19f1d8c7628f9dadfd6 sphincs-sha2-192s-robust +13efa67b9297afa051b9b30e2686266350c8b4000caa49aa432516e2a86d0b68 sphincs-sha2-192s-simple +dc3330f8f19c816f45ee9a1127bf2b8a8c900e05df9a964bb760f0adf8f9b1b3 sphincs-sha2-256f-robust +46e286dc1a20012789c1bf4793a8eb2043dd0c11df729fa36d9f96b0aeffdac6 sphincs-sha2-256f-simple +1f42b407e1e351861ba23e520b1974f399e349fcb66c614d727a38fb4e646634 sphincs-sha2-256s-robust +c816ca365a667e4d6564a95ac576bc9d7be0de7e66eff93e6f05dd4f134a183f sphincs-sha2-256s-simple +4be71430814589ce7c861030c7cdce0aa73f75885b693b41fdb7c34d8f32fa79 sphincs-shake-128f-robust +5167df2ce46f33b76ccf0688f7769217d91878bd7d9b431080a3032eba51da10 sphincs-shake-128f-simple +fbe6c99d6ccc42fc9af5babbac532f28288d4164b182515dffeb1cd47f351d12 sphincs-shake-128s-robust +e7d5caee1941be99b6dfe46a95fc4535a34792f429e61d1cdc7fd3bbafe9ff02 sphincs-shake-128s-simple +243d0e25de08fea547b0beae5f778a48bd55e56066435f9cdb9afc60a722699e sphincs-shake-192f-robust +f204fd1cd5dce187441d104ae7159b64322b6a4afae708d48dc9966fe418ec4e sphincs-shake-192f-simple +cb13eaa2b1c074f53c87f1025e6bb1b356ad8de3bea9388b90a058a6460766bb sphincs-shake-192s-robust +4cc01c4a562d738ac54f5abfead35ecc4f46a1e2531fa12b4bc2819f4560c351 sphincs-shake-192s-simple +5a736aeba47f8d84e3ca47126715affcb4ce6cef13e3c9f6af220827973aa383 sphincs-shake-256f-robust +127f7ab83c740344546fe30777b221e8cb39f30fc4242d07d7608dc31a9835d4 sphincs-shake-256f-simple +4d2ca7d10f2206c3cb9a26c6b00a0361601a1fe2dddf102fbfd6d3dac0be10fe sphincs-shake-256s-robust +4ce4552e2e9b009a9016eb6dbcbefae3da2de151d61e2f392d4b9517eaeab91d sphincs-shake-256s-simple diff --git a/benchmark.py b/benchmark.py new file mode 100755 index 0000000..4ae6003 --- /dev/null +++ b/benchmark.py @@ -0,0 +1,39 @@ +#! /usr/bin/env python3 +import fileinput +import itertools +import os +import sys +from subprocess import DEVNULL, run + +implementations = [ + ('ref', ['shake', 'sha2', 'haraka']), + ('haraka-aesni', ['haraka']), + ('shake-avx2', ['shake']), + ('sha2-avx2', ['sha2']), + ] + +options = ["f", "s"] +sizes = [128, 192, 256] +thashes = ['robust', 'simple'] + +for impl, fns in implementations: + params = os.path.join(impl, "params.h") + for fn in fns: + for opt, size, thash in itertools.product(options, sizes, thashes): + paramset = "sphincs-{}-{}{}".format(fn, size, opt) + paramfile = "params-{}.h".format(paramset) + + print("Benchmarking", paramset, thash, "using", impl, flush=True) + + params = 'PARAMS={}'.format(paramset) # overrides Makefile var + thash = 'THASH={}'.format(thash) # overrides Makefile var + + run(["make", "-C", impl, "clean", thash, params], + stdout=DEVNULL, stderr=sys.stderr) + run(["make", "-C", impl, "benchmarks", thash, params], + stdout=DEVNULL, stderr=sys.stderr) + run(["make", "-C", impl, "benchmark", thash, params], + stdout=sys.stdout, stderr=sys.stderr) + + print(flush=True) + diff --git a/haraka-aesni/.gitignore b/haraka-aesni/.gitignore new file mode 100644 index 0000000..67bcef9 --- /dev/null +++ b/haraka-aesni/.gitignore @@ -0,0 +1,5 @@ +test/* +!test/*.c +PQCsignKAT_*.rsp +PQCsignKAT_*.req +PQCgenKAT_sign diff --git a/haraka-aesni/Makefile b/haraka-aesni/Makefile new file mode 100644 index 0000000..a5c5816 --- /dev/null +++ b/haraka-aesni/Makefile @@ -0,0 +1,47 @@ +PARAMS = sphincs-haraka-128f +THASH = robust + +CC = /usr/bin/gcc +CFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3 -std=c99 -march=native -fomit-frame-pointer -flto -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) + + +SOURCES = hash_haraka.c hash_harakax4.c thash_haraka_$(THASH).c thash_haraka_$(THASH)x4.c address.c randombytes.c merkle.c wots.c utils.c utilsx4.c fors.c sign.c haraka.c +HEADERS = params.h hash.h hashx4.h thash.h thashx4.h address.h randombytes.h merkle.c wots.h utils.h utilsx4.h fors.h api.h haraka.h harakax4.h + +DET_SOURCES = $(SOURCES:randombytes.%=rng.%) +DET_HEADERS = $(HEADERS:randombytes.%=rng.%) + +TESTS = test/fors \ + test/spx \ + +BENCHMARK = test/benchmark + +.PHONY: clean test benchmark + +default: PQCgenKAT_sign + +all: PQCgenKAT_sign tests benchmarks + +tests: $(TESTS) + +test: $(TESTS:=.exec) + +benchmarks: $(BENCHMARK) + +benchmark: $(BENCHMARK:=.exec) + +PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) + $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto + +test/%: test/%.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) + +test/%.exec: test/% + @$< + +clean: + -$(RM) $(TESTS) + -$(RM) $(BENCHMARK) + -$(RM) PQCgenKAT_sign + -$(RM) PQCsignKAT_*.rsp + -$(RM) PQCsignKAT_*.req diff --git a/haraka-aesni/PQCgenKAT_sign.c b/haraka-aesni/PQCgenKAT_sign.c new file mode 120000 index 0000000..a17dbe2 --- /dev/null +++ b/haraka-aesni/PQCgenKAT_sign.c @@ -0,0 +1 @@ +../ref/PQCgenKAT_sign.c \ No newline at end of file diff --git a/haraka-aesni/address.c b/haraka-aesni/address.c new file mode 120000 index 0000000..02c52c6 --- /dev/null +++ b/haraka-aesni/address.c @@ -0,0 +1 @@ +../ref/address.c \ No newline at end of file diff --git a/haraka-aesni/address.h b/haraka-aesni/address.h new file mode 120000 index 0000000..e670da5 --- /dev/null +++ b/haraka-aesni/address.h @@ -0,0 +1 @@ +../ref/address.h \ No newline at end of file diff --git a/haraka-aesni/api.h b/haraka-aesni/api.h new file mode 120000 index 0000000..ea89e0a --- /dev/null +++ b/haraka-aesni/api.h @@ -0,0 +1 @@ +../ref/api.h \ No newline at end of file diff --git a/haraka-aesni/context.h b/haraka-aesni/context.h new file mode 100644 index 0000000..f88445a --- /dev/null +++ b/haraka-aesni/context.h @@ -0,0 +1,16 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "immintrin.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#endif diff --git a/haraka-aesni/fors.c b/haraka-aesni/fors.c new file mode 120000 index 0000000..abd8d52 --- /dev/null +++ b/haraka-aesni/fors.c @@ -0,0 +1 @@ +../shake-avx2/fors.c \ No newline at end of file diff --git a/haraka-aesni/fors.h b/haraka-aesni/fors.h new file mode 120000 index 0000000..07156bd --- /dev/null +++ b/haraka-aesni/fors.h @@ -0,0 +1 @@ +../ref/fors.h \ No newline at end of file diff --git a/haraka-aesni/haraka.c b/haraka-aesni/haraka.c new file mode 100644 index 0000000..2d01db8 --- /dev/null +++ b/haraka-aesni/haraka.c @@ -0,0 +1,720 @@ +/* +Plain C implementation of the Haraka256 and Haraka512 permutations. +*/ +#include +#include +#include +#include +#include + +#include "haraka.h" +#include "harakax4.h" +#include "utils.h" + +#define HARAKAS_RATE 32 + +#define u64 unsigned long +#define u128 __m128i + +#define LOAD(src) _mm_loadu_si128((u128 *)(src)) +#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) + +#define XOR128(a, b) _mm_xor_si128(a, b) + +#define AES2(s0, s1, rci) \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ + s1 = _mm_aesenc_si128(s1, *(rci + 1)); \ + s0 = _mm_aesenc_si128(s0, *(rci + 2)); \ + s1 = _mm_aesenc_si128(s1, *(rci + 3)); + +#define AES2_4x(s0, s1, s2, s3, rci) \ + AES2(s0[0], s0[1], rci); \ + AES2(s1[0], s1[1], rci); \ + AES2(s2[0], s2[1], rci); \ + AES2(s3[0], s3[1], rci); + +#define AES4(s0, s1, s2, s3, rci) \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ + s1 = _mm_aesenc_si128(s1, *(rci + 1)); \ + s2 = _mm_aesenc_si128(s2, *(rci + 2)); \ + s3 = _mm_aesenc_si128(s3, *(rci + 3)); \ + s0 = _mm_aesenc_si128(s0, *(rci + 4)); \ + s1 = _mm_aesenc_si128(s1, *(rci + 5)); \ + s2 = _mm_aesenc_si128(s2, *(rci + 6)); \ + s3 = _mm_aesenc_si128(s3, *(rci + 7)); + +#define AES4_4x(s0, s1, s2, s3, rci) \ + AES4(s0[0], s0[1], s0[2], s0[3], rci); \ + AES4(s1[0], s1[1], s1[2], s1[3], rci); \ + AES4(s2[0], s2[1], s2[2], s2[3], rci); \ + AES4(s3[0], s3[1], s3[2], s3[3], rci); + +#define MIX2(s0, s1) \ + tmp = _mm_unpacklo_epi32(s0, s1); \ + s1 = _mm_unpackhi_epi32(s0, s1); \ + s0 = tmp; + +#define MIX4(s0, s1, s2, s3) \ + tmp = _mm_unpacklo_epi32(s0, s1); \ + s0 = _mm_unpackhi_epi32(s0, s1); \ + s1 = _mm_unpacklo_epi32(s2, s3); \ + s2 = _mm_unpackhi_epi32(s2, s3); \ + s3 = _mm_unpacklo_epi32(s0, s2); \ + s0 = _mm_unpackhi_epi32(s0, s2); \ + s2 = _mm_unpackhi_epi32(s1, tmp); \ + s1 = _mm_unpacklo_epi32(s1, tmp); + +#define TRUNCSTORE(out, s0, s1, s2, s3) \ + _mm_storeu_si128((u128 *)out, \ + _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ + _mm_storeu_si128((u128 *)(out + 16), \ + _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); + +static void load_haraka_constants(u128 *rc) +{ + rc[0] = _mm_set_epi32(0x0684704c,0xe620c00a,0xb2c5fef0,0x75817b9d); + rc[1] = _mm_set_epi32(0x8b66b4e1,0x88f3a06b,0x640f6ba4,0x2f08f717); + rc[2] = _mm_set_epi32(0x3402de2d,0x53f28498,0xcf029d60,0x9f029114); + rc[3] = _mm_set_epi32(0x0ed6eae6,0x2e7b4f08,0xbbf3bcaf,0xfd5b4f79); + rc[4] = _mm_set_epi32(0xcbcfb0cb,0x4872448b,0x79eecd1c,0xbe397044); + rc[5] = _mm_set_epi32(0x7eeacdee,0x6e9032b7,0x8d5335ed,0x2b8a057b); + rc[6] = _mm_set_epi32(0x67c28f43,0x5e2e7cd0,0xe2412761,0xda4fef1b); + rc[7] = _mm_set_epi32(0x2924d9b0,0xafcacc07,0x675ffde2,0x1fc70b3b); + rc[8] = _mm_set_epi32(0xab4d63f1,0xe6867fe9,0xecdb8fca,0xb9d465ee); + rc[9] = _mm_set_epi32(0x1c30bf84,0xd4b7cd64,0x5b2a404f,0xad037e33); + rc[10] = _mm_set_epi32(0xb2cc0bb9,0x941723bf,0x69028b2e,0x8df69800); + rc[11] = _mm_set_epi32(0xfa0478a6,0xde6f5572,0x4aaa9ec8,0x5c9d2d8a); + rc[12] = _mm_set_epi32(0xdfb49f2b,0x6b772a12,0x0efa4f2e,0x29129fd4); + rc[13] = _mm_set_epi32(0x1ea10344,0xf449a236,0x32d611ae,0xbb6a12ee); + rc[14] = _mm_set_epi32(0xaf044988,0x4b050084,0x5f9600c9,0x9ca8eca6); + rc[15] = _mm_set_epi32(0x21025ed8,0x9d199c4f,0x78a2c7e3,0x27e593ec); + rc[16] = _mm_set_epi32(0xbf3aaaf8,0xa759c9b7,0xb9282ecd,0x82d40173); + rc[17] = _mm_set_epi32(0x6260700d,0x6186b017,0x37f2efd9,0x10307d6b); + rc[18] = _mm_set_epi32(0x5aca45c2,0x21300443,0x81c29153,0xf6fc9ac6); + rc[19] = _mm_set_epi32(0x9223973c,0x226b68bb,0x2caf92e8,0x36d1943a); + rc[20] = _mm_set_epi32(0xd3bf9238,0x225886eb,0x6cbab958,0xe51071b4); + rc[21] = _mm_set_epi32(0xdb863ce5,0xaef0c677,0x933dfddd,0x24e1128d); + rc[22] = _mm_set_epi32(0xbb606268,0xffeba09c,0x83e48de3,0xcb2212b1); + rc[23] = _mm_set_epi32(0x734bd3dc,0xe2e4d19c,0x2db91a4e,0xc72bf77d); + rc[24] = _mm_set_epi32(0x43bb47c3,0x61301b43,0x4b1415c4,0x2cb3924e); + rc[25] = _mm_set_epi32(0xdba775a8,0xe707eff6,0x03b231dd,0x16eb6899); + rc[26] = _mm_set_epi32(0x6df3614b,0x3c755977,0x8e5e2302,0x7eca472c); + rc[27] = _mm_set_epi32(0xcda75a17,0xd6de7d77,0x6d1be5b9,0xb88617f9); + rc[28] = _mm_set_epi32(0xec6b43f0,0x6ba8e9aa,0x9d6c069d,0xa946ee5d); + rc[29] = _mm_set_epi32(0xcb1e6950,0xf957332b,0xa2531159,0x3bf327c1); + rc[30] = _mm_set_epi32(0x2cee0c75,0x00da619c,0xe4ed0353,0x600ed0d9); + rc[31] = _mm_set_epi32(0xf0b1a5a1,0x96e90cab,0x80bbbabc,0x63a4a350); + rc[32] = _mm_set_epi32(0xae3db102,0x5e962988,0xab0dde30,0x938dca39); + rc[33] = _mm_set_epi32(0x17bb8f38,0xd554a40b,0x8814f3a8,0x2e75b442); + rc[34] = _mm_set_epi32(0x34bb8a5b,0x5f427fd7,0xaeb6b779,0x360a16f6); + rc[35] = _mm_set_epi32(0x26f65241,0xcbe55438,0x43ce5918,0xffbaafde); + rc[36] = _mm_set_epi32(0x4ce99a54,0xb9f3026a,0xa2ca9cf7,0x839ec978); + rc[37] = _mm_set_epi32(0xae51a51a,0x1bdff7be,0x40c06e28,0x22901235); + rc[38] = _mm_set_epi32(0xa0c1613c,0xba7ed22b,0xc173bc0f,0x48a659cf); + rc[39] = _mm_set_epi32(0x756acc03,0x02288288,0x4ad6bdfd,0xe9c59da1); +} + +void tweak_constants(spx_ctx *ctx) +{ + int i; + unsigned char buf[40*16]; + + /* Use the standard constants to generate tweaked ones. */ + load_haraka_constants(ctx->rc); + + /* Constants for pk.seed */ + haraka_S(buf, 40*16, ctx->pub_seed, SPX_N, ctx); + + /* Tweak constants with the pub_seed */ + for (i = 0; i < 40; i++) { + ctx->rc[i] = LOAD(buf + i*16); + } +} + +static void haraka_S_absorb(unsigned char *s, unsigned int r, + const unsigned char *m, unsigned long long mlen, + unsigned char p, const spx_ctx *ctx) +{ + unsigned long long i; + SPX_VLA(unsigned char, t, r); + + while (mlen >= r) { + // XOR block to state + STORE(s, XOR128(LOAD(s), LOAD(m))); + STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; + } + + for (i = 0; i < r; ++i) { + t[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t[i] = m[i]; + } + t[i] = p; + t[r - 1] |= 128; + STORE(s, XOR128(LOAD(s), LOAD(t))); + STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); +} + +static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p, + const spx_ctx *ctx) +{ + unsigned long long i; + SPX_VLA(unsigned char, t0, r); + SPX_VLA(unsigned char, t1, r); + SPX_VLA(unsigned char, t2, r); + SPX_VLA(unsigned char, t3, r); + + while (mlen >= r) { + // XOR block to state + STORE(s, XOR128(LOAD(s), LOAD(m0))); + STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); + STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); + STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); + STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); + STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); + STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); + STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); + + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + STORE(s, XOR128(LOAD(s), LOAD(t0))); + STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); + STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); + STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); + STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); + STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); + STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); + STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); +} + +static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, + unsigned char *s, unsigned int r, + const spx_ctx *ctx) +{ + while (nblocks > 0) { + haraka512_perm(s, s, ctx); + STORE(h, LOAD(s)); + STORE(h + 16, LOAD(s + 16)); + h += r; + nblocks--; + } +} + +static void haraka_S_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long nblocks, + unsigned char *s, + unsigned int r, + const spx_ctx *ctx) +{ + while (nblocks > 0) { + haraka512_perm_x4(s, s, ctx); + STORE(h0, LOAD(s)); + STORE(h0 + 16, LOAD(s + 16)); + STORE(h1, LOAD(s + 64)); + STORE(h1 + 16, LOAD(s + 80)); + STORE(h2, LOAD(s + 128)); + STORE(h2 + 16, LOAD(s + 144)); + STORE(h3, LOAD(s + 192)); + STORE(h3 + 16, LOAD(s + 208)); + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + +void haraka_S_inc_init(uint8_t *s_inc) +{ + size_t i; + + for (i = 0; i < 64; i++) { + s_inc[i] = 0; + } + s_inc[64] = 0; +} + +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) +{ + size_t i; + + /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ + while (mlen + s_inc[64] >= HARAKAS_RATE) { + for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { + /* Take the i'th byte from message + xor with the s_inc[64] + i'th byte of the state */ + s_inc[s_inc[64] + i] ^= m[i]; + } + mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); + m += HARAKAS_RATE - s_inc[64]; + s_inc[64] = 0; + + haraka512_perm(s_inc, s_inc, ctx); + } + + for (i = 0; i < mlen; i++) { + s_inc[s_inc[64] + i] ^= m[i]; + } + s_inc[64] += mlen; +} + +void haraka_S_inc_finalize(uint8_t *s_inc) +{ + /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, + so we can always use one more byte for p in the current state. */ + s_inc[s_inc[64]] ^= 0x1F; + s_inc[HARAKAS_RATE - 1] ^= 128; + s_inc[64] = 0; +} + +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) +{ + size_t i; + + /* First consume any bytes we still have sitting around */ + for (i = 0; i < outlen && i < s_inc[64]; i++) { + /* There are s_inc[64] bytes left, so r - s_inc[64] is the first + available byte. We consume from there, i.e., up to r. */ + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + } + out += i; + outlen -= i; + s_inc[64] -= i; + + /* Then squeeze the remaining necessary blocks */ + while (outlen > 0) { + haraka512_perm(s_inc, s_inc, ctx); + + for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { + out[i] = s_inc[i]; + } + out += i; + outlen -= i; + s_inc[64] = HARAKAS_RATE - i; + } +} + +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) +{ + unsigned long long i; + unsigned char s[64]; + unsigned char d[32]; + + for (i = 0; i < 64; i++) { + s[i] = 0; + } + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); + + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); + out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; + + if (outlen % HARAKAS_RATE) { + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); + for (i = 0; i < outlen % HARAKAS_RATE; i++) { + out[i] = d[i]; + } + } +} + +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) +{ + unsigned long long i; + unsigned char s[64 * 4]; + unsigned char d0[32]; + unsigned char d1[32]; + unsigned char d2[32]; + unsigned char d3[32]; + + for (i = 0; i < 64 * 4; i++) { + s[i] = 0; + } + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); + + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); + out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; + out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; + out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; + out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; + + if (outlen % HARAKAS_RATE) { + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); + for (i = 0; i < outlen % HARAKAS_RATE; i++) { + out0[i] = d0[i]; + out1[i] = d1[i]; + out2[i] = d2[i]; + out3[i] = d3[i]; + } + } +} + +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) +{ + u128 s[4], tmp; + + s[0] = LOAD(in); + s[1] = LOAD(in + 16); + s[2] = LOAD(in + 32); + s[3] = LOAD(in + 48); + + AES4(s[0], s[1], s[2], s[3], ctx->rc); + MIX4(s[0], s[1], s[2], s[3]); + + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); + MIX4(s[0], s[1], s[2], s[3]); + + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); + MIX4(s[0], s[1], s[2], s[3]); + + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); + MIX4(s[0], s[1], s[2], s[3]); + + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); + MIX4(s[0], s[1], s[2], s[3]); + + STORE(out, s[0]); + STORE(out + 16, s[1]); + STORE(out + 32, s[2]); + STORE(out + 48, s[3]); +} + +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) +{ + u128 s[4][4], tmp; + + s[0][0] = LOAD(in); + s[0][1] = LOAD(in + 16); + s[0][2] = LOAD(in + 32); + s[0][3] = LOAD(in + 48); + s[1][0] = LOAD(in + 64); + s[1][1] = LOAD(in + 80); + s[1][2] = LOAD(in + 96); + s[1][3] = LOAD(in + 112); + s[2][0] = LOAD(in + 128); + s[2][1] = LOAD(in + 144); + s[2][2] = LOAD(in + 160); + s[2][3] = LOAD(in + 176); + s[3][0] = LOAD(in + 192); + s[3][1] = LOAD(in + 208); + s[3][2] = LOAD(in + 224); + s[3][3] = LOAD(in + 240); + + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); + MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); + MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); + MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); + MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); + + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); + MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); + MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); + MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); + MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); + + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); + MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); + MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); + MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); + MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); + + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); + MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); + MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); + MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); + MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); + + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); + MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); + MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); + MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); + MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); + + STORE(out, s[0][0]); + STORE(out + 16, s[0][1]); + STORE(out + 32, s[0][2]); + STORE(out + 48, s[0][3]); + STORE(out + 64, s[1][0]); + STORE(out + 80, s[1][1]); + STORE(out + 96, s[1][2]); + STORE(out + 112, s[1][3]); + STORE(out + 128, s[2][0]); + STORE(out + 144, s[2][1]); + STORE(out + 160, s[2][2]); + STORE(out + 176, s[2][3]); + STORE(out + 192, s[3][0]); + STORE(out + 208, s[3][1]); + STORE(out + 224, s[3][2]); + STORE(out + 240, s[3][3]); +} + +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) +{ + u128 s[4], tmp; + + s[0] = LOAD(in); + s[1] = LOAD(in + 16); + s[2] = LOAD(in + 32); + s[3] = LOAD(in + 48); + + AES4(s[0], s[1], s[2], s[3], ctx->rc); + MIX4(s[0], s[1], s[2], s[3]); + + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); + MIX4(s[0], s[1], s[2], s[3]); + + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); + MIX4(s[0], s[1], s[2], s[3]); + + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); + MIX4(s[0], s[1], s[2], s[3]); + + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); + MIX4(s[0], s[1], s[2], s[3]); + + s[0] = XOR128(s[0], LOAD(in)); + s[1] = XOR128(s[1], LOAD(in + 16)); + s[2] = XOR128(s[2], LOAD(in + 32)); + s[3] = XOR128(s[3], LOAD(in + 48)); + + // truncate and store result + TRUNCSTORE(out, s[0], s[1], s[2], s[3]); +} + +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) +{ + u128 s[4][4], tmp; + + s[0][0] = LOAD(in); + s[0][1] = LOAD(in + 16); + s[0][2] = LOAD(in + 32); + s[0][3] = LOAD(in + 48); + s[1][0] = LOAD(in + 64); + s[1][1] = LOAD(in + 80); + s[1][2] = LOAD(in + 96); + s[1][3] = LOAD(in + 112); + s[2][0] = LOAD(in + 128); + s[2][1] = LOAD(in + 144); + s[2][2] = LOAD(in + 160); + s[2][3] = LOAD(in + 176); + s[3][0] = LOAD(in + 192); + s[3][1] = LOAD(in + 208); + s[3][2] = LOAD(in + 224); + s[3][3] = LOAD(in + 240); + + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); + MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); + MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); + MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); + MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); + + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); + MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); + MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); + MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); + MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); + + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); + MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); + MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); + MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); + MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); + + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); + MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); + MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); + MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); + MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); + + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); + MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); + MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); + MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); + MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); + + s[0][0] = XOR128(s[0][0], LOAD(in)); + s[0][1] = XOR128(s[0][1], LOAD(in + 16)); + s[0][2] = XOR128(s[0][2], LOAD(in + 32)); + s[0][3] = XOR128(s[0][3], LOAD(in + 48)); + s[1][0] = XOR128(s[1][0], LOAD(in + 64)); + s[1][1] = XOR128(s[1][1], LOAD(in + 80)); + s[1][2] = XOR128(s[1][2], LOAD(in + 96)); + s[1][3] = XOR128(s[1][3], LOAD(in + 112)); + s[2][0] = XOR128(s[2][0], LOAD(in + 128)); + s[2][1] = XOR128(s[2][1], LOAD(in + 144)); + s[2][2] = XOR128(s[2][2], LOAD(in + 160)); + s[2][3] = XOR128(s[2][3], LOAD(in + 176)); + s[3][0] = XOR128(s[3][0], LOAD(in + 192)); + s[3][1] = XOR128(s[3][1], LOAD(in + 208)); + s[3][2] = XOR128(s[3][2], LOAD(in + 224)); + s[3][3] = XOR128(s[3][3], LOAD(in + 240)); + + TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); + TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); + TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); + TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); +} + +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) +{ + u128 s[2], tmp; + + s[0] = LOAD(in); + s[1] = LOAD(in + 16); + + AES2(s[0], s[1], ctx->rc); + MIX2(s[0], s[1]); + + AES2(s[0], s[1], ctx->rc + 4); + MIX2(s[0], s[1]); + + AES2(s[0], s[1], ctx->rc + 8); + MIX2(s[0], s[1]); + + AES2(s[0], s[1], ctx->rc + 12); + MIX2(s[0], s[1]); + + AES2(s[0], s[1], ctx->rc + 16); + MIX2(s[0], s[1]); + + s[0] = XOR128(s[0], LOAD(in)); + s[1] = XOR128(s[1], LOAD(in + 16)); + + STORE(out, s[0]); + STORE(out + 16, s[1]); +} + +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) +{ + u128 s[4][2], tmp; + + s[0][0] = LOAD(in); + s[0][1] = LOAD(in + 16); + s[1][0] = LOAD(in + 32); + s[1][1] = LOAD(in + 48); + s[2][0] = LOAD(in + 64); + s[2][1] = LOAD(in + 80); + s[3][0] = LOAD(in + 96); + s[3][1] = LOAD(in + 112); + + // Round 1 + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); + + MIX2(s[0][0], s[0][1]); + MIX2(s[1][0], s[1][1]); + MIX2(s[2][0], s[2][1]); + MIX2(s[3][0], s[3][1]); + + // Round 2 + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); + + MIX2(s[0][0], s[0][1]); + MIX2(s[1][0], s[1][1]); + MIX2(s[2][0], s[2][1]); + MIX2(s[3][0], s[3][1]); + + // Round 3 + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); + + MIX2(s[0][0], s[0][1]); + MIX2(s[1][0], s[1][1]); + MIX2(s[2][0], s[2][1]); + MIX2(s[3][0], s[3][1]); + + // Round 4 + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); + + MIX2(s[0][0], s[0][1]); + MIX2(s[1][0], s[1][1]); + MIX2(s[2][0], s[2][1]); + MIX2(s[3][0], s[3][1]); + + // Round 5 + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); + + MIX2(s[0][0], s[0][1]); + MIX2(s[1][0], s[1][1]); + MIX2(s[2][0], s[2][1]); + MIX2(s[3][0], s[3][1]); + + // Feed Forward + s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); + s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); + s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); + s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); + s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); + s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); + s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); + s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); + + STORE(out, s[0][0]); + STORE(out + 16, s[0][1]); + STORE(out + 32, s[1][0]); + STORE(out + 48, s[1][1]); + STORE(out + 64, s[2][0]); + STORE(out + 80, s[2][1]); + STORE(out + 96, s[3][0]); + STORE(out + 112, s[3][1]); +} diff --git a/haraka-aesni/haraka.h b/haraka-aesni/haraka.h new file mode 120000 index 0000000..0378b1e --- /dev/null +++ b/haraka-aesni/haraka.h @@ -0,0 +1 @@ +../ref/haraka.h \ No newline at end of file diff --git a/haraka-aesni/haraka_offsets.h b/haraka-aesni/haraka_offsets.h new file mode 120000 index 0000000..cb6abf9 --- /dev/null +++ b/haraka-aesni/haraka_offsets.h @@ -0,0 +1 @@ +../ref/haraka_offsets.h \ No newline at end of file diff --git a/haraka-aesni/harakax4.h b/haraka-aesni/harakax4.h new file mode 100644 index 0000000..2a18650 --- /dev/null +++ b/haraka-aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/haraka-aesni/hash.h b/haraka-aesni/hash.h new file mode 120000 index 0000000..cffc52b --- /dev/null +++ b/haraka-aesni/hash.h @@ -0,0 +1 @@ +../ref/hash.h \ No newline at end of file diff --git a/haraka-aesni/hash_haraka.c b/haraka-aesni/hash_haraka.c new file mode 120000 index 0000000..6c5febe --- /dev/null +++ b/haraka-aesni/hash_haraka.c @@ -0,0 +1 @@ +../ref/hash_haraka.c \ No newline at end of file diff --git a/haraka-aesni/hash_harakax4.c b/haraka-aesni/hash_harakax4.c new file mode 100644 index 0000000..e970078 --- /dev/null +++ b/haraka-aesni/hash_harakax4.c @@ -0,0 +1,36 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "harakax4.h" +#include "hashx4.h" + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4*8]) +{ + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ + unsigned char outbuf[4 * 32]; + unsigned int i; + + for (i = 0; i < 4; i++) { + memcpy(bufx4 + i*64, addrx4 + i*8, SPX_ADDR_BYTES); + memcpy(bufx4 + i*64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + } + + haraka512x4(outbuf, bufx4, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); +} diff --git a/haraka-aesni/hashx4.h b/haraka-aesni/hashx4.h new file mode 120000 index 0000000..3dc1ba4 --- /dev/null +++ b/haraka-aesni/hashx4.h @@ -0,0 +1 @@ +../shake-avx2/hashx4.h \ No newline at end of file diff --git a/haraka-aesni/merkle.c b/haraka-aesni/merkle.c new file mode 120000 index 0000000..7a8454d --- /dev/null +++ b/haraka-aesni/merkle.c @@ -0,0 +1 @@ +../shake-avx2/merkle.c \ No newline at end of file diff --git a/haraka-aesni/merkle.h b/haraka-aesni/merkle.h new file mode 120000 index 0000000..7d167ed --- /dev/null +++ b/haraka-aesni/merkle.h @@ -0,0 +1 @@ +../ref/merkle.h \ No newline at end of file diff --git a/haraka-aesni/params.h b/haraka-aesni/params.h new file mode 120000 index 0000000..53133cc --- /dev/null +++ b/haraka-aesni/params.h @@ -0,0 +1 @@ +../ref/params.h \ No newline at end of file diff --git a/haraka-aesni/params/params-sphincs-haraka-128f.h b/haraka-aesni/params/params-sphincs-haraka-128f.h new file mode 120000 index 0000000..4e5417f --- /dev/null +++ b/haraka-aesni/params/params-sphincs-haraka-128f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-haraka-128f.h \ No newline at end of file diff --git a/haraka-aesni/params/params-sphincs-haraka-128s.h b/haraka-aesni/params/params-sphincs-haraka-128s.h new file mode 120000 index 0000000..686aa8c --- /dev/null +++ b/haraka-aesni/params/params-sphincs-haraka-128s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-haraka-128s.h \ No newline at end of file diff --git a/haraka-aesni/params/params-sphincs-haraka-192f.h b/haraka-aesni/params/params-sphincs-haraka-192f.h new file mode 120000 index 0000000..14971bf --- /dev/null +++ b/haraka-aesni/params/params-sphincs-haraka-192f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-haraka-192f.h \ No newline at end of file diff --git a/haraka-aesni/params/params-sphincs-haraka-192s.h b/haraka-aesni/params/params-sphincs-haraka-192s.h new file mode 120000 index 0000000..3361225 --- /dev/null +++ b/haraka-aesni/params/params-sphincs-haraka-192s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-haraka-192s.h \ No newline at end of file diff --git a/haraka-aesni/params/params-sphincs-haraka-256f.h b/haraka-aesni/params/params-sphincs-haraka-256f.h new file mode 120000 index 0000000..28d6862 --- /dev/null +++ b/haraka-aesni/params/params-sphincs-haraka-256f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-haraka-256f.h \ No newline at end of file diff --git a/haraka-aesni/params/params-sphincs-haraka-256s.h b/haraka-aesni/params/params-sphincs-haraka-256s.h new file mode 120000 index 0000000..233ce46 --- /dev/null +++ b/haraka-aesni/params/params-sphincs-haraka-256s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-haraka-256s.h \ No newline at end of file diff --git a/haraka-aesni/randombytes.c b/haraka-aesni/randombytes.c new file mode 120000 index 0000000..59a42a5 --- /dev/null +++ b/haraka-aesni/randombytes.c @@ -0,0 +1 @@ +../ref/randombytes.c \ No newline at end of file diff --git a/haraka-aesni/randombytes.h b/haraka-aesni/randombytes.h new file mode 120000 index 0000000..055e443 --- /dev/null +++ b/haraka-aesni/randombytes.h @@ -0,0 +1 @@ +../ref/randombytes.h \ No newline at end of file diff --git a/haraka-aesni/rng.c b/haraka-aesni/rng.c new file mode 120000 index 0000000..6e2fdac --- /dev/null +++ b/haraka-aesni/rng.c @@ -0,0 +1 @@ +../ref/rng.c \ No newline at end of file diff --git a/haraka-aesni/rng.h b/haraka-aesni/rng.h new file mode 120000 index 0000000..d678c7c --- /dev/null +++ b/haraka-aesni/rng.h @@ -0,0 +1 @@ +../ref/rng.h \ No newline at end of file diff --git a/haraka-aesni/sign.c b/haraka-aesni/sign.c new file mode 120000 index 0000000..42fea88 --- /dev/null +++ b/haraka-aesni/sign.c @@ -0,0 +1 @@ +../ref/sign.c \ No newline at end of file diff --git a/haraka-aesni/test/benchmark.c b/haraka-aesni/test/benchmark.c new file mode 100644 index 0000000..1c87297 --- /dev/null +++ b/haraka-aesni/test/benchmark.c @@ -0,0 +1,162 @@ +#define _POSIX_C_SOURCE 199309L + +#include +#include +#include + +#include "../api.h" +#include "../fors.h" +#include "../wotsx4.h" +#include "../params.h" +#include "../randombytes.h" + +#define SPX_MLEN 32 +#define NTESTS 10 + +static void wots_gen_pkx4(unsigned char* pk, const spx_ctx *ctx, + uint32_t addr[8]); + +static int cmp_llu(const void *a, const void*b) +{ + if(*(unsigned long long *)a < *(unsigned long long *)b) return -1; + if(*(unsigned long long *)a > *(unsigned long long *)b) return 1; + return 0; +} + +static unsigned long long median(unsigned long long *l, size_t llen) +{ + qsort(l,llen,sizeof(unsigned long long),cmp_llu); + + if(llen%2) return l[llen/2]; + else return (l[llen/2-1]+l[llen/2])/2; +} + +static void delta(unsigned long long *l, size_t llen) +{ + unsigned int i; + for(i = 0; i < llen - 1; i++) { + l[i] = l[i+1] - l[i]; + } +} + +static unsigned long long cpucycles(void) +{ + unsigned long long result; + __asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax" + : "=a" (result) :: "%rdx"); + return result; +} + +static void printfcomma (unsigned long long n) +{ + if (n < 1000) { + printf("%llu", n); + return; + } + printfcomma(n / 1000); + printf (",%03llu", n % 1000); +} + +static void printfalignedcomma (unsigned long long n, int len) +{ + unsigned long long ncopy = n; + int i = 0; + + while (ncopy > 9) { + len -= 1; + ncopy /= 10; + i += 1; // to account for commas + } + i = i/3 - 1; // to account for commas + for (; i < len; i++) { + printf(" "); + } + printfcomma(n); +} + +static void display_result(double result, unsigned long long *l, size_t llen, unsigned long long mul) +{ + unsigned long long med; + + result /= NTESTS; + delta(l, NTESTS + 1); + med = median(l, llen); + printf("avg. %11.2lf us (%2.2lf sec); median ", result, result / 1e6); + printfalignedcomma(med, 12); + printf(" cycles, %5llux: ", mul); + printfalignedcomma(mul*med, 12); + printf(" cycles\n"); +} + +#define MEASURE(TEXT, MUL, FNCALL)\ + printf(TEXT);\ + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);\ + for(i = 0; i < NTESTS; i++) {\ + t[i] = cpucycles();\ + FNCALL;\ + }\ + t[NTESTS] = cpucycles();\ + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop);\ + result = (stop.tv_sec - start.tv_sec) * 1e6 + (stop.tv_nsec - start.tv_nsec) / 1e3;\ + display_result(result, t, NTESTS, MUL); + +int main(void) +{ + /* Make stdout buffer more responsive. */ + setbuf(stdout, NULL); + + spx_ctx ctx; + unsigned char pk[SPX_PK_BYTES]; + unsigned char sk[SPX_SK_BYTES]; + unsigned char *m = malloc(SPX_MLEN); + unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); + unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); + + unsigned char fors_pk[SPX_FORS_PK_BYTES]; + unsigned char fors_m[SPX_FORS_MSG_BYTES]; + unsigned char fors_sig[SPX_FORS_BYTES]; + unsigned char addr[SPX_ADDR_BYTES]; + + unsigned char wots_pk[SPX_WOTS_PK_BYTES]; + + unsigned long long smlen; + unsigned long long mlen; + unsigned long long t[NTESTS+1]; + struct timespec start, stop; + double result; + int i; + + randombytes(m, SPX_MLEN); + randombytes(addr, SPX_ADDR_BYTES); + + printf("Parameters: n = %d, h = %d, d = %d, b = %d, k = %d, w = %d\n", + SPX_N, SPX_FULL_HEIGHT, SPX_D, SPX_FORS_HEIGHT, SPX_FORS_TREES, + SPX_WOTS_W); + + printf("Running %d iterations.\n", NTESTS); + + MEASURE("Generating keypair.. ", 1, crypto_sign_keypair(pk, sk)); + MEASURE(" - WOTS pk gen.. ", (1 << SPX_TREE_HEIGHT), wots_gen_pkx4(wots_pk, &ctx, (uint32_t *) addr)); + MEASURE("Signing.. ", 1, crypto_sign(sm, &smlen, m, SPX_MLEN, sk)); + MEASURE(" - FORS signing.. ", 1, fors_sign(fors_sig, fors_pk, fors_m, &ctx, (uint32_t *) addr)); + MEASURE(" - WOTS pk gen.. ", SPX_D * (1 << SPX_TREE_HEIGHT), wots_gen_pkx4(wots_pk, &ctx, (uint32_t *) addr)); + MEASURE("Verifying.. ", 1, crypto_sign_open(mout, &mlen, sm, smlen, pk)); + + printf("Signature size: %d (%.2f KiB)\n", SPX_BYTES, SPX_BYTES / 1024.0); + printf("Public key size: %d (%.2f KiB)\n", SPX_PK_BYTES, SPX_PK_BYTES / 1024.0); + printf("Secret key size: %d (%.2f KiB)\n", SPX_SK_BYTES, SPX_SK_BYTES / 1024.0); + + free(m); + free(sm); + free(mout); + + return 0; +} + +static void wots_gen_pkx4(unsigned char *pk, const spx_ctx *ctx, + uint32_t addr[8]) { + struct leaf_info_x4 leaf; + unsigned steps[ SPX_WOTS_LEN ] = { 0 }; + INITIALIZE_LEAF_INFO_X4(leaf, addr, steps); + wots_gen_leafx4(pk, ctx, 0, &leaf); +} diff --git a/haraka-aesni/test/fors.c b/haraka-aesni/test/fors.c new file mode 120000 index 0000000..b2bccee --- /dev/null +++ b/haraka-aesni/test/fors.c @@ -0,0 +1 @@ +../../ref/test/fors.c \ No newline at end of file diff --git a/haraka-aesni/test/spx.c b/haraka-aesni/test/spx.c new file mode 120000 index 0000000..7af26df --- /dev/null +++ b/haraka-aesni/test/spx.c @@ -0,0 +1 @@ +../../ref/test/spx.c \ No newline at end of file diff --git a/haraka-aesni/thash.h b/haraka-aesni/thash.h new file mode 120000 index 0000000..937dd48 --- /dev/null +++ b/haraka-aesni/thash.h @@ -0,0 +1 @@ +../ref/thash.h \ No newline at end of file diff --git a/haraka-aesni/thash_haraka_robust.c b/haraka-aesni/thash_haraka_robust.c new file mode 120000 index 0000000..156c18d --- /dev/null +++ b/haraka-aesni/thash_haraka_robust.c @@ -0,0 +1 @@ +../ref/thash_haraka_robust.c \ No newline at end of file diff --git a/haraka-aesni/thash_haraka_robustx4.c b/haraka-aesni/thash_haraka_robustx4.c new file mode 100644 index 0000000..15d19f1 --- /dev/null +++ b/haraka-aesni/thash_haraka_robustx4.c @@ -0,0 +1,93 @@ +#include +#include + +#include "thashx4.h" +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "harakax4.h" + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4*8]) +{ + SPX_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, bitmask0, inblocks * SPX_N); + SPX_VLA(unsigned char, bitmask1, inblocks * SPX_N); + SPX_VLA(unsigned char, bitmask2, inblocks * SPX_N); + SPX_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + unsigned int i; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + // Generate masks first in buffer + memcpy(buf_tmp, addrx4 + 0*8, 32); + memcpy(buf_tmp + 32, addrx4 + 1*8, 32); + memcpy(buf_tmp + 64, addrx4 + 2*8, 32); + memcpy(buf_tmp + 96, addrx4 + 3*8, 32); + + haraka256x4(outbuf, buf_tmp, ctx); + + /* move addresses to make room for inputs; zero old values */ + memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); + memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); + memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); + /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ + + /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ + memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); + /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ + memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); + + for (i = 0; i < SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; + buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; + buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; + buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; + } + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0*8, 32); + memcpy(buf1, addrx4 + 1*8, 32); + memcpy(buf2, addrx4 + 2*8, 32); + memcpy(buf3, addrx4 + 3*8, 32); + + haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks*SPX_N, + ctx); + } +} diff --git a/haraka-aesni/thash_haraka_simple.c b/haraka-aesni/thash_haraka_simple.c new file mode 120000 index 0000000..4d3c767 --- /dev/null +++ b/haraka-aesni/thash_haraka_simple.c @@ -0,0 +1 @@ +../ref/thash_haraka_simple.c \ No newline at end of file diff --git a/haraka-aesni/thash_haraka_simplex4.c b/haraka-aesni/thash_haraka_simplex4.c new file mode 100644 index 0000000..841d445 --- /dev/null +++ b/haraka-aesni/thash_haraka_simplex4.c @@ -0,0 +1,67 @@ +#include +#include + +#include "thashx4.h" +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "harakax4.h" + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4*8]) +{ + SPX_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks*SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + memcpy(buf_tmp, addrx4 + 0*8, 32); + memcpy(buf_tmp + 64, addrx4 + 1*8, 32); + memcpy(buf_tmp + 128, addrx4 + 2*8, 32); + memcpy(buf_tmp + 192, addrx4 + 3*8, 32); + + memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0*8, 32); + memcpy(buf1, addrx4 + 1*8, 32); + memcpy(buf2, addrx4 + 2*8, 32); + memcpy(buf3, addrx4 + 3*8, 32); + + memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks*SPX_N, + ctx); + } +} diff --git a/haraka-aesni/thashx4.h b/haraka-aesni/thashx4.h new file mode 120000 index 0000000..982555e --- /dev/null +++ b/haraka-aesni/thashx4.h @@ -0,0 +1 @@ +../shake-avx2/thashx4.h \ No newline at end of file diff --git a/haraka-aesni/utils.c b/haraka-aesni/utils.c new file mode 120000 index 0000000..e8ef6eb --- /dev/null +++ b/haraka-aesni/utils.c @@ -0,0 +1 @@ +../ref/utils.c \ No newline at end of file diff --git a/haraka-aesni/utils.h b/haraka-aesni/utils.h new file mode 120000 index 0000000..51b0d39 --- /dev/null +++ b/haraka-aesni/utils.h @@ -0,0 +1 @@ +../ref/utils.h \ No newline at end of file diff --git a/haraka-aesni/utilsx4.c b/haraka-aesni/utilsx4.c new file mode 120000 index 0000000..ea6a5cf --- /dev/null +++ b/haraka-aesni/utilsx4.c @@ -0,0 +1 @@ +../shake-avx2/utilsx4.c \ No newline at end of file diff --git a/haraka-aesni/utilsx4.h b/haraka-aesni/utilsx4.h new file mode 120000 index 0000000..faf4c28 --- /dev/null +++ b/haraka-aesni/utilsx4.h @@ -0,0 +1 @@ +../shake-avx2/utilsx4.h \ No newline at end of file diff --git a/haraka-aesni/wots.c b/haraka-aesni/wots.c new file mode 120000 index 0000000..07845f1 --- /dev/null +++ b/haraka-aesni/wots.c @@ -0,0 +1 @@ +../shake-avx2/wots.c \ No newline at end of file diff --git a/haraka-aesni/wots.h b/haraka-aesni/wots.h new file mode 120000 index 0000000..8c327ea --- /dev/null +++ b/haraka-aesni/wots.h @@ -0,0 +1 @@ +../ref/wots.h \ No newline at end of file diff --git a/haraka-aesni/wotsx4.h b/haraka-aesni/wotsx4.h new file mode 120000 index 0000000..db76d0f --- /dev/null +++ b/haraka-aesni/wotsx4.h @@ -0,0 +1 @@ +../shake-avx2/wotsx4.h \ No newline at end of file diff --git a/ref/.gitignore b/ref/.gitignore new file mode 100644 index 0000000..67bcef9 --- /dev/null +++ b/ref/.gitignore @@ -0,0 +1,5 @@ +test/* +!test/*.c +PQCsignKAT_*.rsp +PQCsignKAT_*.req +PQCgenKAT_sign diff --git a/ref/Makefile b/ref/Makefile new file mode 100644 index 0000000..a3aabad --- /dev/null +++ b/ref/Makefile @@ -0,0 +1,65 @@ +PARAMS = sphincs-haraka-128f +THASH = robust + +CC=/usr/bin/gcc +CFLAGS=-Wall -Wextra -Wpedantic -O3 -std=c99 -Wconversion -Wmissing-prototypes -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) + +SOURCES = address.c randombytes.c merkle.c wots.c wotsx1.c utils.c utilsx1.c fors.c sign.c +HEADERS = params.h address.h randombytes.h merkle.h wots.h wotsx1.h utils.h utilsx1.h fors.h api.h hash.h thash.h + +ifneq (,$(findstring shake,$(PARAMS))) + SOURCES += fips202.c hash_shake.c thash_shake_$(THASH).c + HEADERS += fips202.h +endif +ifneq (,$(findstring haraka,$(PARAMS))) + SOURCES += haraka.c hash_haraka.c thash_haraka_$(THASH).c + HEADERS += haraka.h +endif +ifneq (,$(findstring sha2,$(PARAMS))) + SOURCES += sha2.c hash_sha2.c thash_sha2_$(THASH).c + HEADERS += sha2.h +endif + +DET_SOURCES = $(SOURCES:randombytes.%=rng.%) +DET_HEADERS = $(HEADERS:randombytes.%=rng.%) + +TESTS = test/fors \ + test/spx \ + +BENCHMARK = test/benchmark + +.PHONY: clean test benchmark + +default: PQCgenKAT_sign + +all: PQCgenKAT_sign tests benchmarks + +tests: $(TESTS) + +test: $(TESTS:=.exec) + +benchmarks: $(BENCHMARK) + +benchmark: $(BENCHMARK:=.exec) + +PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) + $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto + +test/benchmark: test/benchmark.c test/cycles.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -o $@ test/cycles.c $(SOURCES) $< $(LDLIBS) + +test/%: test/%.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) + +test/haraka: test/haraka.c $(filter-out haraka.c,$(SOURCES)) $(HEADERS) + $(CC) $(CFLAGS) -o $@ $(filter-out haraka.c,$(SOURCES)) $< $(LDLIBS) + +test/%.exec: test/% + @$< + +clean: + -$(RM) $(TESTS) + -$(RM) $(BENCHMARK) + -$(RM) PQCgenKAT_sign + -$(RM) PQCsignKAT_*.rsp + -$(RM) PQCsignKAT_*.req diff --git a/ref/PQCgenKAT_sign.c b/ref/PQCgenKAT_sign.c new file mode 100644 index 0000000..16f41c1 --- /dev/null +++ b/ref/PQCgenKAT_sign.c @@ -0,0 +1,262 @@ + +// +// PQCgenKAT_sign.c +// +// Created by Bassham, Lawrence E (Fed) on 8/29/17. +// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. +// +#include +#include +#include +#include +#include "rng.h" +#include "api.h" + +#define MAX_MARKER_LEN 50 + +#define KAT_SUCCESS 0 +#define KAT_FILE_OPEN_ERROR -1 +#define KAT_DATA_ERROR -3 +#define KAT_CRYPTO_FAILURE -4 + +int FindMarker(FILE *infile, const char *marker); +int ReadHex(FILE *infile, unsigned char *A, int Length, char *str); +void fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L); + +char AlgName[] = "My Alg Name"; + +int +main(void) +{ + char fn_req[32], fn_rsp[32]; + FILE *fp_req, *fp_rsp; + unsigned char seed[48]; + unsigned char msg[3300]; + unsigned char entropy_input[48]; + unsigned char *m, *sm, *m1; + unsigned long long mlen, smlen, mlen1; + int count; + int done; + unsigned char pk[CRYPTO_PUBLICKEYBYTES], sk[CRYPTO_SECRETKEYBYTES]; + int ret_val; + + // Create the REQUEST file + sprintf(fn_req, "PQCsignKAT_%d.req", CRYPTO_SECRETKEYBYTES); + if ( (fp_req = fopen(fn_req, "w")) == NULL ) { + printf("Couldn't open <%s> for write\n", fn_req); + return KAT_FILE_OPEN_ERROR; + } + sprintf(fn_rsp, "PQCsignKAT_%d.rsp", CRYPTO_SECRETKEYBYTES); + if ( (fp_rsp = fopen(fn_rsp, "w")) == NULL ) { + printf("Couldn't open <%s> for write\n", fn_rsp); + return KAT_FILE_OPEN_ERROR; + } + + for (int i=0; i<48; i++) + entropy_input[i] = (unsigned char)i; + + randombytes_init(entropy_input, NULL); + for (int i=0; i<100; i++) { + fprintf(fp_req, "count = %d\n", i); + randombytes(seed, 48); + fprintBstr(fp_req, "seed = ", seed, 48); + mlen = (unsigned long long int)(33*(i+1)); + fprintf(fp_req, "mlen = %llu\n", mlen); + randombytes(msg, mlen); + fprintBstr(fp_req, "msg = ", msg, mlen); + fprintf(fp_req, "pk =\n"); + fprintf(fp_req, "sk =\n"); + fprintf(fp_req, "smlen =\n"); + fprintf(fp_req, "sm =\n\n"); + } + fclose(fp_req); + + //Create the RESPONSE file based on what's in the REQUEST file + if ( (fp_req = fopen(fn_req, "r")) == NULL ) { + printf("Couldn't open <%s> for read\n", fn_req); + return KAT_FILE_OPEN_ERROR; + } + + fprintf(fp_rsp, "# %s\n\n", CRYPTO_ALGNAME); + done = 0; + do { + if ( FindMarker(fp_req, "count = ") ) + ret_val = fscanf(fp_req, "%d", &count); + else { + done = 1; + break; + } + fprintf(fp_rsp, "count = %d\n", count); + + if ( !ReadHex(fp_req, seed, 48, "seed = ") ) { + printf("ERROR: unable to read 'seed' from <%s>\n", fn_req); + return KAT_DATA_ERROR; + } + fprintBstr(fp_rsp, "seed = ", seed, 48); + + randombytes_init(seed, NULL); + + if ( FindMarker(fp_req, "mlen = ") ) + ret_val = fscanf(fp_req, "%llu", &mlen); + else { + printf("ERROR: unable to read 'mlen' from <%s>\n", fn_req); + return KAT_DATA_ERROR; + } + fprintf(fp_rsp, "mlen = %llu\n", mlen); + + m = (unsigned char *)calloc(mlen, sizeof(unsigned char)); + m1 = (unsigned char *)calloc(mlen+CRYPTO_BYTES, sizeof(unsigned char)); + sm = (unsigned char *)calloc(mlen+CRYPTO_BYTES, sizeof(unsigned char)); + + if ( !ReadHex(fp_req, m, (int)mlen, "msg = ") ) { + printf("ERROR: unable to read 'msg' from <%s>\n", fn_req); + return KAT_DATA_ERROR; + } + fprintBstr(fp_rsp, "msg = ", m, mlen); + + // Generate the public/private keypair + if ( (ret_val = crypto_sign_keypair(pk, sk)) != 0) { + printf("crypto_sign_keypair returned <%d>\n", ret_val); + return KAT_CRYPTO_FAILURE; + } + fprintBstr(fp_rsp, "pk = ", pk, CRYPTO_PUBLICKEYBYTES); + fprintBstr(fp_rsp, "sk = ", sk, CRYPTO_SECRETKEYBYTES); + + if ( (ret_val = crypto_sign(sm, &smlen, m, mlen, sk)) != 0) { + printf("crypto_sign returned <%d>\n", ret_val); + return KAT_CRYPTO_FAILURE; + } + fprintf(fp_rsp, "smlen = %llu\n", smlen); + fprintBstr(fp_rsp, "sm = ", sm, smlen); + fprintf(fp_rsp, "\n"); + + if ( (ret_val = crypto_sign_open(m1, &mlen1, sm, smlen, pk)) != 0) { + printf("crypto_sign_open returned <%d>\n", ret_val); + return KAT_CRYPTO_FAILURE; + } + + if ( mlen != mlen1 ) { + printf("crypto_sign_open returned bad 'mlen': Got <%llu>, expected <%llu>\n", mlen1, mlen); + return KAT_CRYPTO_FAILURE; + } + + if ( memcmp(m, m1, mlen) ) { + printf("crypto_sign_open returned bad 'm' value\n"); + return KAT_CRYPTO_FAILURE; + } + + free(m); + free(m1); + free(sm); + + } while ( !done ); + + fclose(fp_req); + fclose(fp_rsp); + + return KAT_SUCCESS; +} + +// +// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.) +// +int +FindMarker(FILE *infile, const char *marker) +{ + char line[MAX_MARKER_LEN]; + size_t i, len; + int curr_line; + + len = strlen(marker); + if ( len > MAX_MARKER_LEN-1 ) + len = MAX_MARKER_LEN-1; + + for ( i=0; i= '0') && (ch <= '9') ) + ich = (unsigned char)(ch - '0'); + else if ( (ch >= 'A') && (ch <= 'F') ) + ich = (unsigned char)(ch - 'A' + 10); + else if ( (ch >= 'a') && (ch <= 'f') ) + ich = (unsigned char)(ch - 'a' + 10); + else // shouldn't ever get here + ich = 0; + + for ( i=0; i> 4)); + A[Length-1] = (unsigned char)((A[Length-1] << 4) | ich); + } + else + return 0; + + return 1; +} + +void +fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L) +{ + unsigned long long i; + + fprintf(fp, "%s", S); + + for ( i=0; i +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) +{ + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) +{ +#if (SPX_TREE_HEIGHT * (SPX_D - 1)) > 64 + #error Subtree addressing is currently limited to at most 2^64 trees +#endif + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) +{ + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) +{ + memcpy( out, in, SPX_OFFSET_TREE+8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) +{ + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_KP_ADDR], keypair); +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) +{ + memcpy( out, in, SPX_OFFSET_TREE+8 ); + memcpy( (unsigned char *)out + SPX_OFFSET_KP_ADDR, (unsigned char *)in + SPX_OFFSET_KP_ADDR, 4); +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) +{ + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) +{ + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) +{ + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) +{ + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/ref/address.h b/ref/address.h new file mode 100644 index 0000000..49f8d66 --- /dev/null +++ b/ref/address.h @@ -0,0 +1,51 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/ref/api.h b/ref/api.h new file mode 100644 index 0000000..d57a148 --- /dev/null +++ b/ref/api.h @@ -0,0 +1,77 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES 3*SPX_N + +/* + * Returns the length of a secret key, in bytes + */ +unsigned long long crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +unsigned long long crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +unsigned long long crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +unsigned long long crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, + const unsigned char *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(unsigned char *m, unsigned long long *mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk); + +#endif diff --git a/ref/context.h b/ref/context.h new file mode 100644 index 0000000..aded564 --- /dev/null +++ b/ref/context.h @@ -0,0 +1,28 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + +#ifdef SPX_SHA2 + // sha256 state that absorbed pub_seed + uint8_t state_seeded[40]; + +# if SPX_SHA512 + // sha512 state that absorbed pub_seed + uint8_t state_seeded_512[72]; +# endif +#endif + +#ifdef SPX_HARAKA + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +#endif +} spx_ctx; + +#endif diff --git a/ref/fips202.c b/ref/fips202.c new file mode 100644 index 0000000..8262d91 --- /dev/null +++ b/ref/fips202.c @@ -0,0 +1,598 @@ +/* Based on the public domain implementation in + * crypto_hash/keccakc512/simple/ from http://bench.cr.yp.to/supercop.html + * by Ronny Van Keer + * and the public domain "TweetFips202" implementation + * from https://twitter.com/tweetfips202 + * by Gilles Van Assche, Daniel J. Bernstein, and Peter Schwabe */ + +#include +#include + +#include "fips202.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64 - (offset)))) + +/************************************************* + * Name: load64 + * + * Description: Load 8 bytes into uint64_t in little-endian order + * + * Arguments: - const uint8_t *x: pointer to input byte array + * + * Returns the loaded 64-bit unsigned integer + **************************************************/ +static uint64_t load64(const uint8_t *x) { + uint64_t r = 0; + for (size_t i = 0; i < 8; ++i) { + r |= (uint64_t)x[i] << 8 * i; + } + + return r; +} + +/************************************************* + * Name: store64 + * + * Description: Store a 64-bit integer to a byte array in little-endian order + * + * Arguments: - uint8_t *x: pointer to the output byte array + * - uint64_t u: input 64-bit unsigned integer + **************************************************/ +static void store64(uint8_t *x, uint64_t u) { + for (size_t i = 0; i < 8; ++i) { + x[i] = (uint8_t) (u >> 8 * i); + } +} + +/* Keccak round constants */ +static const uint64_t KeccakF_RoundConstants[NROUNDS] = { + 0x0000000000000001ULL, 0x0000000000008082ULL, + 0x800000000000808aULL, 0x8000000080008000ULL, + 0x000000000000808bULL, 0x0000000080000001ULL, + 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x000000000000008aULL, 0x0000000000000088ULL, + 0x0000000080008009ULL, 0x000000008000000aULL, + 0x000000008000808bULL, 0x800000000000008bULL, + 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, + 0x000000000000800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, + 0x0000000080000001ULL, 0x8000000080008008ULL +}; + +/************************************************* + * Name: KeccakF1600_StatePermute + * + * Description: The Keccak F1600 Permutation + * + * Arguments: - uint64_t *state: pointer to input/output Keccak state + **************************************************/ +static void KeccakF1600_StatePermute(uint64_t *state) { + int round; + + uint64_t Aba, Abe, Abi, Abo, Abu; + uint64_t Aga, Age, Agi, Ago, Agu; + uint64_t Aka, Ake, Aki, Ako, Aku; + uint64_t Ama, Ame, Ami, Amo, Amu; + uint64_t Asa, Ase, Asi, Aso, Asu; + uint64_t BCa, BCe, BCi, BCo, BCu; + uint64_t Da, De, Di, Do, Du; + uint64_t Eba, Ebe, Ebi, Ebo, Ebu; + uint64_t Ega, Ege, Egi, Ego, Egu; + uint64_t Eka, Eke, Eki, Eko, Eku; + uint64_t Ema, Eme, Emi, Emo, Emu; + uint64_t Esa, Ese, Esi, Eso, Esu; + + // copyFromState(A, state) + Aba = state[0]; + Abe = state[1]; + Abi = state[2]; + Abo = state[3]; + Abu = state[4]; + Aga = state[5]; + Age = state[6]; + Agi = state[7]; + Ago = state[8]; + Agu = state[9]; + Aka = state[10]; + Ake = state[11]; + Aki = state[12]; + Ako = state[13]; + Aku = state[14]; + Ama = state[15]; + Ame = state[16]; + Ami = state[17]; + Amo = state[18]; + Amu = state[19]; + Asa = state[20]; + Ase = state[21]; + Asi = state[22]; + Aso = state[23]; + Asu = state[24]; + + for (round = 0; round < NROUNDS; round += 2) { + // prepareTheta + BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa; + BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase; + BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; + BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; + BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; + + // thetaRhoPiChiIotaPrepareTheta(round , A, E) + Da = BCu ^ ROL(BCe, 1); + De = BCa ^ ROL(BCi, 1); + Di = BCe ^ ROL(BCo, 1); + Do = BCi ^ ROL(BCu, 1); + Du = BCo ^ ROL(BCa, 1); + + Aba ^= Da; + BCa = Aba; + Age ^= De; + BCe = ROL(Age, 44); + Aki ^= Di; + BCi = ROL(Aki, 43); + Amo ^= Do; + BCo = ROL(Amo, 21); + Asu ^= Du; + BCu = ROL(Asu, 14); + Eba = BCa ^ ((~BCe) & BCi); + Eba ^= KeccakF_RoundConstants[round]; + Ebe = BCe ^ ((~BCi) & BCo); + Ebi = BCi ^ ((~BCo) & BCu); + Ebo = BCo ^ ((~BCu) & BCa); + Ebu = BCu ^ ((~BCa) & BCe); + + Abo ^= Do; + BCa = ROL(Abo, 28); + Agu ^= Du; + BCe = ROL(Agu, 20); + Aka ^= Da; + BCi = ROL(Aka, 3); + Ame ^= De; + BCo = ROL(Ame, 45); + Asi ^= Di; + BCu = ROL(Asi, 61); + Ega = BCa ^ ((~BCe) & BCi); + Ege = BCe ^ ((~BCi) & BCo); + Egi = BCi ^ ((~BCo) & BCu); + Ego = BCo ^ ((~BCu) & BCa); + Egu = BCu ^ ((~BCa) & BCe); + + Abe ^= De; + BCa = ROL(Abe, 1); + Agi ^= Di; + BCe = ROL(Agi, 6); + Ako ^= Do; + BCi = ROL(Ako, 25); + Amu ^= Du; + BCo = ROL(Amu, 8); + Asa ^= Da; + BCu = ROL(Asa, 18); + Eka = BCa ^ ((~BCe) & BCi); + Eke = BCe ^ ((~BCi) & BCo); + Eki = BCi ^ ((~BCo) & BCu); + Eko = BCo ^ ((~BCu) & BCa); + Eku = BCu ^ ((~BCa) & BCe); + + Abu ^= Du; + BCa = ROL(Abu, 27); + Aga ^= Da; + BCe = ROL(Aga, 36); + Ake ^= De; + BCi = ROL(Ake, 10); + Ami ^= Di; + BCo = ROL(Ami, 15); + Aso ^= Do; + BCu = ROL(Aso, 56); + Ema = BCa ^ ((~BCe) & BCi); + Eme = BCe ^ ((~BCi) & BCo); + Emi = BCi ^ ((~BCo) & BCu); + Emo = BCo ^ ((~BCu) & BCa); + Emu = BCu ^ ((~BCa) & BCe); + + Abi ^= Di; + BCa = ROL(Abi, 62); + Ago ^= Do; + BCe = ROL(Ago, 55); + Aku ^= Du; + BCi = ROL(Aku, 39); + Ama ^= Da; + BCo = ROL(Ama, 41); + Ase ^= De; + BCu = ROL(Ase, 2); + Esa = BCa ^ ((~BCe) & BCi); + Ese = BCe ^ ((~BCi) & BCo); + Esi = BCi ^ ((~BCo) & BCu); + Eso = BCo ^ ((~BCu) & BCa); + Esu = BCu ^ ((~BCa) & BCe); + + // prepareTheta + BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa; + BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; + BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; + BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; + BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; + + // thetaRhoPiChiIotaPrepareTheta(round+1, E, A) + Da = BCu ^ ROL(BCe, 1); + De = BCa ^ ROL(BCi, 1); + Di = BCe ^ ROL(BCo, 1); + Do = BCi ^ ROL(BCu, 1); + Du = BCo ^ ROL(BCa, 1); + + Eba ^= Da; + BCa = Eba; + Ege ^= De; + BCe = ROL(Ege, 44); + Eki ^= Di; + BCi = ROL(Eki, 43); + Emo ^= Do; + BCo = ROL(Emo, 21); + Esu ^= Du; + BCu = ROL(Esu, 14); + Aba = BCa ^ ((~BCe) & BCi); + Aba ^= KeccakF_RoundConstants[round + 1]; + Abe = BCe ^ ((~BCi) & BCo); + Abi = BCi ^ ((~BCo) & BCu); + Abo = BCo ^ ((~BCu) & BCa); + Abu = BCu ^ ((~BCa) & BCe); + + Ebo ^= Do; + BCa = ROL(Ebo, 28); + Egu ^= Du; + BCe = ROL(Egu, 20); + Eka ^= Da; + BCi = ROL(Eka, 3); + Eme ^= De; + BCo = ROL(Eme, 45); + Esi ^= Di; + BCu = ROL(Esi, 61); + Aga = BCa ^ ((~BCe) & BCi); + Age = BCe ^ ((~BCi) & BCo); + Agi = BCi ^ ((~BCo) & BCu); + Ago = BCo ^ ((~BCu) & BCa); + Agu = BCu ^ ((~BCa) & BCe); + + Ebe ^= De; + BCa = ROL(Ebe, 1); + Egi ^= Di; + BCe = ROL(Egi, 6); + Eko ^= Do; + BCi = ROL(Eko, 25); + Emu ^= Du; + BCo = ROL(Emu, 8); + Esa ^= Da; + BCu = ROL(Esa, 18); + Aka = BCa ^ ((~BCe) & BCi); + Ake = BCe ^ ((~BCi) & BCo); + Aki = BCi ^ ((~BCo) & BCu); + Ako = BCo ^ ((~BCu) & BCa); + Aku = BCu ^ ((~BCa) & BCe); + + Ebu ^= Du; + BCa = ROL(Ebu, 27); + Ega ^= Da; + BCe = ROL(Ega, 36); + Eke ^= De; + BCi = ROL(Eke, 10); + Emi ^= Di; + BCo = ROL(Emi, 15); + Eso ^= Do; + BCu = ROL(Eso, 56); + Ama = BCa ^ ((~BCe) & BCi); + Ame = BCe ^ ((~BCi) & BCo); + Ami = BCi ^ ((~BCo) & BCu); + Amo = BCo ^ ((~BCu) & BCa); + Amu = BCu ^ ((~BCa) & BCe); + + Ebi ^= Di; + BCa = ROL(Ebi, 62); + Ego ^= Do; + BCe = ROL(Ego, 55); + Eku ^= Du; + BCi = ROL(Eku, 39); + Ema ^= Da; + BCo = ROL(Ema, 41); + Ese ^= De; + BCu = ROL(Ese, 2); + Asa = BCa ^ ((~BCe) & BCi); + Ase = BCe ^ ((~BCi) & BCo); + Asi = BCi ^ ((~BCo) & BCu); + Aso = BCo ^ ((~BCu) & BCa); + Asu = BCu ^ ((~BCa) & BCe); + } + + // copyToState(state, A) + state[0] = Aba; + state[1] = Abe; + state[2] = Abi; + state[3] = Abo; + state[4] = Abu; + state[5] = Aga; + state[6] = Age; + state[7] = Agi; + state[8] = Ago; + state[9] = Agu; + state[10] = Aka; + state[11] = Ake; + state[12] = Aki; + state[13] = Ako; + state[14] = Aku; + state[15] = Ama; + state[16] = Ame; + state[17] = Ami; + state[18] = Amo; + state[19] = Amu; + state[20] = Asa; + state[21] = Ase; + state[22] = Asi; + state[23] = Aso; + state[24] = Asu; +} + +/************************************************* + * Name: keccak_absorb + * + * Description: Absorb step of Keccak; + * non-incremental, starts by zeroeing the state. + * + * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + * - const uint8_t *m: pointer to input to be absorbed into s + * - size_t mlen: length of input in bytes + * - uint8_t p: domain-separation byte for different + * Keccak-derived functions + **************************************************/ +static void keccak_absorb(uint64_t *s, uint32_t r, const uint8_t *m, + size_t mlen, uint8_t p) { + size_t i; + uint8_t t[200]; + + /* Zero state */ + for (i = 0; i < 25; ++i) { + s[i] = 0; + } + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[i] ^= load64(m + 8 * i); + } + + KeccakF1600_StatePermute(s); + mlen -= r; + m += r; + } + + for (i = 0; i < r; ++i) { + t[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t[i] = m[i]; + } + t[i] = p; + t[r - 1] |= 128; + for (i = 0; i < r / 8; ++i) { + s[i] ^= load64(t + 8 * i); + } +} + +/************************************************* + * Name: keccak_squeezeblocks + * + * Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each. + * Modifies the state. Can be called multiple times to keep + * squeezing, i.e., is incremental. + * + * Arguments: - uint8_t *h: pointer to output blocks + * - size_t nblocks: number of blocks to be + * squeezed (written to h) + * - uint64_t *s: pointer to input/output Keccak state + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + **************************************************/ +static void keccak_squeezeblocks(uint8_t *h, size_t nblocks, + uint64_t *s, uint32_t r) { + while (nblocks > 0) { + KeccakF1600_StatePermute(s); + for (size_t i = 0; i < (r >> 3); i++) { + store64(h + 8 * i, s[i]); + } + h += r; + nblocks--; + } +} + +/************************************************* + * Name: keccak_inc_init + * + * Description: Initializes the incremental Keccak state to zero. + * + * Arguments: - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + **************************************************/ +static void keccak_inc_init(uint64_t *s_inc) { + size_t i; + + for (i = 0; i < 25; ++i) { + s_inc[i] = 0; + } + s_inc[25] = 0; +} + +/************************************************* + * Name: keccak_inc_absorb + * + * Description: Incremental keccak absorb + * Preceded by keccak_inc_init, succeeded by keccak_inc_finalize + * + * Arguments: - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + * - const uint8_t *m: pointer to input to be absorbed into s + * - size_t mlen: length of input in bytes + **************************************************/ +static void keccak_inc_absorb(uint64_t *s_inc, uint32_t r, const uint8_t *m, + size_t mlen) { + size_t i; + + /* Recall that s_inc[25] is the non-absorbed bytes xored into the state */ + while (mlen + s_inc[25] >= r) { + for (i = 0; i < r - s_inc[25]; i++) { + /* Take the i'th byte from message + xor with the s_inc[25] + i'th byte of the state; little-endian */ + s_inc[(s_inc[25] + i) >> 3] ^= (uint64_t)m[i] << (8 * ((s_inc[25] + i) & 0x07)); + } + mlen -= (size_t)(r - s_inc[25]); + m += r - s_inc[25]; + s_inc[25] = 0; + + KeccakF1600_StatePermute(s_inc); + } + + for (i = 0; i < mlen; i++) { + s_inc[(s_inc[25] + i) >> 3] ^= (uint64_t)m[i] << (8 * ((s_inc[25] + i) & 0x07)); + } + s_inc[25] += mlen; +} + +/************************************************* + * Name: keccak_inc_finalize + * + * Description: Finalizes Keccak absorb phase, prepares for squeezing + * + * Arguments: - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + * - uint8_t p: domain-separation byte for different + * Keccak-derived functions + **************************************************/ +static void keccak_inc_finalize(uint64_t *s_inc, uint32_t r, uint8_t p) { + /* After keccak_inc_absorb, we are guaranteed that s_inc[25] < r, + so we can always use one more byte for p in the current state. */ + s_inc[s_inc[25] >> 3] ^= (uint64_t)p << (8 * (s_inc[25] & 0x07)); + s_inc[(r - 1) >> 3] ^= (uint64_t)128 << (8 * ((r - 1) & 0x07)); + s_inc[25] = 0; +} + +/************************************************* + * Name: keccak_inc_squeeze + * + * Description: Incremental Keccak squeeze; can be called on byte-level + * + * Arguments: - uint8_t *h: pointer to output bytes + * - size_t outlen: number of bytes to be squeezed + * - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + **************************************************/ +static void keccak_inc_squeeze(uint8_t *h, size_t outlen, + uint64_t *s_inc, uint32_t r) { + size_t i; + + /* First consume any bytes we still have sitting around */ + for (i = 0; i < outlen && i < s_inc[25]; i++) { + /* There are s_inc[25] bytes left, so r - s_inc[25] is the first + available byte. We consume from there, i.e., up to r. */ + h[i] = (uint8_t)(s_inc[(r - s_inc[25] + i) >> 3] >> (8 * ((r - s_inc[25] + i) & 0x07))); + } + h += i; + outlen -= i; + s_inc[25] -= i; + + /* Then squeeze the remaining necessary blocks */ + while (outlen > 0) { + KeccakF1600_StatePermute(s_inc); + + for (i = 0; i < outlen && i < r; i++) { + h[i] = (uint8_t)(s_inc[i >> 3] >> (8 * (i & 0x07))); + } + h += i; + outlen -= i; + s_inc[25] = r - i; + } +} + +void shake256_inc_init(uint64_t *s_inc) { + keccak_inc_init(s_inc); +} + +void shake256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen) { + keccak_inc_absorb(s_inc, SHAKE256_RATE, input, inlen); +} + +void shake256_inc_finalize(uint64_t *s_inc) { + keccak_inc_finalize(s_inc, SHAKE256_RATE, 0x1F); +} + +void shake256_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc) { + keccak_inc_squeeze(output, outlen, s_inc, SHAKE256_RATE); +} + +/************************************************* + * Name: shake256_absorb + * + * Description: Absorb step of the SHAKE256 XOF. + * non-incremental, starts by zeroeing the state. + * + * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state + * - const uint8_t *input: pointer to input to be absorbed + * into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256_absorb(uint64_t *s, const uint8_t *input, size_t inlen) { + keccak_absorb(s, SHAKE256_RATE, input, inlen, 0x1F); +} + +/************************************************* + * Name: shake256_squeezeblocks + * + * Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of + * SHAKE256_RATE bytes each. Modifies the state. Can be called + * multiple times to keep squeezing, i.e., is incremental. + * + * Arguments: - uint8_t *output: pointer to output blocks + * - size_t nblocks: number of blocks to be squeezed + * (written to output) + * - uint64_t *s: pointer to input/output Keccak state + **************************************************/ +void shake256_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s) { + keccak_squeezeblocks(output, nblocks, s, SHAKE256_RATE); +} + +/************************************************* + * Name: shake256 + * + * Description: SHAKE256 XOF with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - size_t outlen: requested output length in bytes + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256(uint8_t *output, size_t outlen, + const uint8_t *input, size_t inlen) { + size_t nblocks = outlen / SHAKE256_RATE; + uint8_t t[SHAKE256_RATE]; + uint64_t s[25]; + + shake256_absorb(s, input, inlen); + shake256_squeezeblocks(output, nblocks, s); + + output += nblocks * SHAKE256_RATE; + outlen -= nblocks * SHAKE256_RATE; + + if (outlen) { + shake256_squeezeblocks(t, 1, s); + for (size_t i = 0; i < outlen; ++i) { + output[i] = t[i]; + } + } +} diff --git a/ref/fips202.h b/ref/fips202.h new file mode 100644 index 0000000..e11cb7f --- /dev/null +++ b/ref/fips202.h @@ -0,0 +1,47 @@ +#ifndef SPX_FIPS202_H +#define SPX_FIPS202_H + +#include +#include + +#define SHAKE128_RATE 168 +#define SHAKE256_RATE 136 +#define SHA3_256_RATE 136 +#define SHA3_512_RATE 72 + +void shake128_absorb(uint64_t *s, const uint8_t *input, size_t inlen); + +void shake128_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s); + +void shake128_inc_init(uint64_t *s_inc); +void shake128_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); +void shake128_inc_finalize(uint64_t *s_inc); +void shake128_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc); + +void shake256_absorb(uint64_t *s, const uint8_t *input, size_t inlen); +void shake256_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s); + +void shake256_inc_init(uint64_t *s_inc); +void shake256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); +void shake256_inc_finalize(uint64_t *s_inc); +void shake256_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc); + +void shake128(uint8_t *output, size_t outlen, + const uint8_t *input, size_t inlen); + +void shake256(uint8_t *output, size_t outlen, + const uint8_t *input, size_t inlen); + +void sha3_256_inc_init(uint64_t *s_inc); +void sha3_256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); +void sha3_256_inc_finalize(uint8_t *output, uint64_t *s_inc); + +void sha3_256(uint8_t *output, const uint8_t *input, size_t inlen); + +void sha3_512_inc_init(uint64_t *s_inc); +void sha3_512_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); +void sha3_512_inc_finalize(uint8_t *output, uint64_t *s_inc); + +void sha3_512(uint8_t *output, const uint8_t *input, size_t inlen); + +#endif diff --git a/ref/fors.c b/ref/fors.c new file mode 100644 index 0000000..e6aa4b4 --- /dev/null +++ b/ref/fors.c @@ -0,0 +1,161 @@ +#include +#include +#include + +#include "fors.h" +#include "utils.h" +#include "utilsx1.h" +#include "hash.h" +#include "thash.h" +#include "address.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) +{ + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) +{ + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) +{ + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) +{ + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= ((m[offset >> 3] >> (offset & 0x7)) & 1u) << j; + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) +{ + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i*SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx* ctx, + const uint32_t fors_addr[8]) +{ + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i*SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/ref/fors.h b/ref/fors.h new file mode 100644 index 0000000..8d98017 --- /dev/null +++ b/ref/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "params.h" +#include "context.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx* ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx* ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/ref/haraka.c b/ref/haraka.c new file mode 100644 index 0000000..b9046f2 --- /dev/null +++ b/ref/haraka.c @@ -0,0 +1,965 @@ +/* + * Constant time implementation of the Haraka hash function. + * + * The bit-sliced implementation of the AES round functions are + * based on the AES implementation in BearSSL written + * by Thomas Pornin , licensed as follows: + * + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#include +#include +#include +#include + +#include "haraka.h" +#include "utils.h" + +#define HARAKAS_RATE 32 + +static const uint64_t haraka512_rc64[10][8] = { + {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, + {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, + {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, + {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, + {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, + {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, + {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, + {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, + {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, + {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, +}; + +static inline uint32_t br_dec32le(const unsigned char *src) +{ + return (uint32_t)src[0] + | ((uint32_t)src[1] << 8) + | ((uint32_t)src[2] << 16) + | ((uint32_t)src[3] << 24); +} + +static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) +{ + while (num-- > 0) { + *v ++ = br_dec32le(src); + src += 4; + } +} + +static inline void br_enc32le(unsigned char *dst, uint32_t x) +{ + dst[0] = (unsigned char)x; + dst[1] = (unsigned char)(x >> 8); + dst[2] = (unsigned char)(x >> 16); + dst[3] = (unsigned char)(x >> 24); +} + + +static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) +{ + while (num-- > 0) { + br_enc32le(dst, *v ++); + dst += 4; + } +} + +static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { + /* + * This S-box implementation is a straightforward translation of + * the circuit described by Boyar and Peralta in "A new + * combinational logic minimization technique with applications + * to cryptology" (https://eprint.iacr.org/2009/191.pdf). + * + * Note that variables x* (input) and s* (output) are numbered + * in "reverse" order (x0 is the high bit, x7 is the low bit). + */ + + uint64_t x0, x1, x2, x3, x4, x5, x6, x7; + uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; + uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; + uint64_t y20, y21; + uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; + uint64_t z10, z11, z12, z13, z14, z15, z16, z17; + uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; + uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; + uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; + uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; + uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; + uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; + uint64_t t60, t61, t62, t63, t64, t65, t66, t67; + uint64_t s0, s1, s2, s3, s4, s5, s6, s7; + + x0 = q[7]; + x1 = q[6]; + x2 = q[5]; + x3 = q[4]; + x4 = q[3]; + x5 = q[2]; + x6 = q[1]; + x7 = q[0]; + + /* + * Top linear transformation. + */ + y14 = x3 ^ x5; + y13 = x0 ^ x6; + y9 = x0 ^ x3; + y8 = x0 ^ x5; + t0 = x1 ^ x2; + y1 = t0 ^ x7; + y4 = y1 ^ x3; + y12 = y13 ^ y14; + y2 = y1 ^ x0; + y5 = y1 ^ x6; + y3 = y5 ^ y8; + t1 = x4 ^ y12; + y15 = t1 ^ x5; + y20 = t1 ^ x1; + y6 = y15 ^ x7; + y10 = y15 ^ t0; + y11 = y20 ^ y9; + y7 = x7 ^ y11; + y17 = y10 ^ y11; + y19 = y10 ^ y8; + y16 = t0 ^ y11; + y21 = y13 ^ y16; + y18 = x0 ^ y16; + + /* + * Non-linear section. + */ + t2 = y12 & y15; + t3 = y3 & y6; + t4 = t3 ^ t2; + t5 = y4 & x7; + t6 = t5 ^ t2; + t7 = y13 & y16; + t8 = y5 & y1; + t9 = t8 ^ t7; + t10 = y2 & y7; + t11 = t10 ^ t7; + t12 = y9 & y11; + t13 = y14 & y17; + t14 = t13 ^ t12; + t15 = y8 & y10; + t16 = t15 ^ t12; + t17 = t4 ^ t14; + t18 = t6 ^ t16; + t19 = t9 ^ t14; + t20 = t11 ^ t16; + t21 = t17 ^ y20; + t22 = t18 ^ y19; + t23 = t19 ^ y21; + t24 = t20 ^ y18; + + t25 = t21 ^ t22; + t26 = t21 & t23; + t27 = t24 ^ t26; + t28 = t25 & t27; + t29 = t28 ^ t22; + t30 = t23 ^ t24; + t31 = t22 ^ t26; + t32 = t31 & t30; + t33 = t32 ^ t24; + t34 = t23 ^ t33; + t35 = t27 ^ t33; + t36 = t24 & t35; + t37 = t36 ^ t34; + t38 = t27 ^ t36; + t39 = t29 & t38; + t40 = t25 ^ t39; + + t41 = t40 ^ t37; + t42 = t29 ^ t33; + t43 = t29 ^ t40; + t44 = t33 ^ t37; + t45 = t42 ^ t41; + z0 = t44 & y15; + z1 = t37 & y6; + z2 = t33 & x7; + z3 = t43 & y16; + z4 = t40 & y1; + z5 = t29 & y7; + z6 = t42 & y11; + z7 = t45 & y17; + z8 = t41 & y10; + z9 = t44 & y12; + z10 = t37 & y3; + z11 = t33 & y4; + z12 = t43 & y13; + z13 = t40 & y5; + z14 = t29 & y2; + z15 = t42 & y9; + z16 = t45 & y14; + z17 = t41 & y8; + + /* + * Bottom linear transformation. + */ + t46 = z15 ^ z16; + t47 = z10 ^ z11; + t48 = z5 ^ z13; + t49 = z9 ^ z10; + t50 = z2 ^ z12; + t51 = z2 ^ z5; + t52 = z7 ^ z8; + t53 = z0 ^ z3; + t54 = z6 ^ z7; + t55 = z16 ^ z17; + t56 = z12 ^ t48; + t57 = t50 ^ t53; + t58 = z4 ^ t46; + t59 = z3 ^ t54; + t60 = t46 ^ t57; + t61 = z14 ^ t57; + t62 = t52 ^ t58; + t63 = t49 ^ t58; + t64 = z4 ^ t59; + t65 = t61 ^ t62; + t66 = z1 ^ t63; + s0 = t59 ^ t63; + s6 = t56 ^ ~t62; + s7 = t48 ^ ~t60; + t67 = t64 ^ t65; + s3 = t53 ^ t66; + s4 = t51 ^ t66; + s5 = t47 ^ t65; + s1 = t64 ^ ~s3; + s2 = t55 ^ ~t67; + + q[7] = s0; + q[6] = s1; + q[5] = s2; + q[4] = s3; + q[3] = s4; + q[2] = s5; + q[1] = s6; + q[0] = s7; +} + +static void br_aes_ct_bitslice_Sbox(uint32_t *q) +{ + /* + * This S-box implementation is a straightforward translation of + * the circuit described by Boyar and Peralta in "A new + * combinational logic minimization technique with applications + * to cryptology" (https://eprint.iacr.org/2009/191.pdf). + * + * Note that variables x* (input) and s* (output) are numbered + * in "reverse" order (x0 is the high bit, x7 is the low bit). + */ + + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; + uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; + uint32_t y20, y21; + uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; + uint32_t z10, z11, z12, z13, z14, z15, z16, z17; + uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; + uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; + uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; + uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; + uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; + uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; + uint32_t t60, t61, t62, t63, t64, t65, t66, t67; + uint32_t s0, s1, s2, s3, s4, s5, s6, s7; + + x0 = q[7]; + x1 = q[6]; + x2 = q[5]; + x3 = q[4]; + x4 = q[3]; + x5 = q[2]; + x6 = q[1]; + x7 = q[0]; + + /* + * Top linear transformation. + */ + y14 = x3 ^ x5; + y13 = x0 ^ x6; + y9 = x0 ^ x3; + y8 = x0 ^ x5; + t0 = x1 ^ x2; + y1 = t0 ^ x7; + y4 = y1 ^ x3; + y12 = y13 ^ y14; + y2 = y1 ^ x0; + y5 = y1 ^ x6; + y3 = y5 ^ y8; + t1 = x4 ^ y12; + y15 = t1 ^ x5; + y20 = t1 ^ x1; + y6 = y15 ^ x7; + y10 = y15 ^ t0; + y11 = y20 ^ y9; + y7 = x7 ^ y11; + y17 = y10 ^ y11; + y19 = y10 ^ y8; + y16 = t0 ^ y11; + y21 = y13 ^ y16; + y18 = x0 ^ y16; + + /* + * Non-linear section. + */ + t2 = y12 & y15; + t3 = y3 & y6; + t4 = t3 ^ t2; + t5 = y4 & x7; + t6 = t5 ^ t2; + t7 = y13 & y16; + t8 = y5 & y1; + t9 = t8 ^ t7; + t10 = y2 & y7; + t11 = t10 ^ t7; + t12 = y9 & y11; + t13 = y14 & y17; + t14 = t13 ^ t12; + t15 = y8 & y10; + t16 = t15 ^ t12; + t17 = t4 ^ t14; + t18 = t6 ^ t16; + t19 = t9 ^ t14; + t20 = t11 ^ t16; + t21 = t17 ^ y20; + t22 = t18 ^ y19; + t23 = t19 ^ y21; + t24 = t20 ^ y18; + + t25 = t21 ^ t22; + t26 = t21 & t23; + t27 = t24 ^ t26; + t28 = t25 & t27; + t29 = t28 ^ t22; + t30 = t23 ^ t24; + t31 = t22 ^ t26; + t32 = t31 & t30; + t33 = t32 ^ t24; + t34 = t23 ^ t33; + t35 = t27 ^ t33; + t36 = t24 & t35; + t37 = t36 ^ t34; + t38 = t27 ^ t36; + t39 = t29 & t38; + t40 = t25 ^ t39; + + t41 = t40 ^ t37; + t42 = t29 ^ t33; + t43 = t29 ^ t40; + t44 = t33 ^ t37; + t45 = t42 ^ t41; + z0 = t44 & y15; + z1 = t37 & y6; + z2 = t33 & x7; + z3 = t43 & y16; + z4 = t40 & y1; + z5 = t29 & y7; + z6 = t42 & y11; + z7 = t45 & y17; + z8 = t41 & y10; + z9 = t44 & y12; + z10 = t37 & y3; + z11 = t33 & y4; + z12 = t43 & y13; + z13 = t40 & y5; + z14 = t29 & y2; + z15 = t42 & y9; + z16 = t45 & y14; + z17 = t41 & y8; + + /* + * Bottom linear transformation. + */ + t46 = z15 ^ z16; + t47 = z10 ^ z11; + t48 = z5 ^ z13; + t49 = z9 ^ z10; + t50 = z2 ^ z12; + t51 = z2 ^ z5; + t52 = z7 ^ z8; + t53 = z0 ^ z3; + t54 = z6 ^ z7; + t55 = z16 ^ z17; + t56 = z12 ^ t48; + t57 = t50 ^ t53; + t58 = z4 ^ t46; + t59 = z3 ^ t54; + t60 = t46 ^ t57; + t61 = z14 ^ t57; + t62 = t52 ^ t58; + t63 = t49 ^ t58; + t64 = z4 ^ t59; + t65 = t61 ^ t62; + t66 = z1 ^ t63; + s0 = t59 ^ t63; + s6 = t56 ^ ~t62; + s7 = t48 ^ ~t60; + t67 = t64 ^ t65; + s3 = t53 ^ t66; + s4 = t51 ^ t66; + s5 = t47 ^ t65; + s1 = t64 ^ ~s3; + s2 = t55 ^ ~t67; + + q[7] = s0; + q[6] = s1; + q[5] = s2; + q[4] = s3; + q[3] = s4; + q[2] = s5; + q[1] = s6; + q[0] = s7; +} + +static void br_aes_ct_ortho(uint32_t *q) +{ +#define SWAPN_32(cl, ch, s, x, y) do { \ + uint32_t a, b; \ + a = (x); \ + b = (y); \ + (x) = (a & (uint32_t)cl) | ((b & (uint32_t)cl) << (s)); \ + (y) = ((a & (uint32_t)ch) >> (s)) | (b & (uint32_t)ch); \ + } while (0) + +#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) +#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) +#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) + + SWAP2_32(q[0], q[1]); + SWAP2_32(q[2], q[3]); + SWAP2_32(q[4], q[5]); + SWAP2_32(q[6], q[7]); + + SWAP4_32(q[0], q[2]); + SWAP4_32(q[1], q[3]); + SWAP4_32(q[4], q[6]); + SWAP4_32(q[5], q[7]); + + SWAP8_32(q[0], q[4]); + SWAP8_32(q[1], q[5]); + SWAP8_32(q[2], q[6]); + SWAP8_32(q[3], q[7]); +} + +static inline void add_round_key32(uint32_t *q, const uint32_t *sk) +{ + q[0] ^= sk[0]; + q[1] ^= sk[1]; + q[2] ^= sk[2]; + q[3] ^= sk[3]; + q[4] ^= sk[4]; + q[5] ^= sk[5]; + q[6] ^= sk[6]; + q[7] ^= sk[7]; +} + +static inline void shift_rows32(uint32_t *q) +{ + int i; + + for (i = 0; i < 8; i++) { + uint32_t x; + + x = q[i]; + q[i] = (x & 0x000000FF) + | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) + | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) + | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); + } +} + +static inline uint32_t rotr16(uint32_t x) +{ + return (x << 16) | (x >> 16); +} + +static inline void mix_columns32(uint32_t *q) +{ + uint32_t q0, q1, q2, q3, q4, q5, q6, q7; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + + q0 = q[0]; + q1 = q[1]; + q2 = q[2]; + q3 = q[3]; + q4 = q[4]; + q5 = q[5]; + q6 = q[6]; + q7 = q[7]; + r0 = (q0 >> 8) | (q0 << 24); + r1 = (q1 >> 8) | (q1 << 24); + r2 = (q2 >> 8) | (q2 << 24); + r3 = (q3 >> 8) | (q3 << 24); + r4 = (q4 >> 8) | (q4 << 24); + r5 = (q5 >> 8) | (q5 << 24); + r6 = (q6 >> 8) | (q6 << 24); + r7 = (q7 >> 8) | (q7 << 24); + + q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); + q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); + q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); + q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); + q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); + q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); + q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); + q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); +} + +static void br_aes_ct64_ortho(uint64_t *q) +{ +#define SWAPN(cl, ch, s, x, y) do { \ + uint64_t a, b; \ + a = (x); \ + b = (y); \ + (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ + (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ + } while (0) + +#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) +#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) +#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) + + SWAP2(q[0], q[1]); + SWAP2(q[2], q[3]); + SWAP2(q[4], q[5]); + SWAP2(q[6], q[7]); + + SWAP4(q[0], q[2]); + SWAP4(q[1], q[3]); + SWAP4(q[4], q[6]); + SWAP4(q[5], q[7]); + + SWAP8(q[0], q[4]); + SWAP8(q[1], q[5]); + SWAP8(q[2], q[6]); + SWAP8(q[3], q[7]); +} + + +static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) +{ + uint64_t x0, x1, x2, x3; + + x0 = w[0]; + x1 = w[1]; + x2 = w[2]; + x3 = w[3]; + x0 |= (x0 << 16); + x1 |= (x1 << 16); + x2 |= (x2 << 16); + x3 |= (x3 << 16); + x0 &= (uint64_t)0x0000FFFF0000FFFF; + x1 &= (uint64_t)0x0000FFFF0000FFFF; + x2 &= (uint64_t)0x0000FFFF0000FFFF; + x3 &= (uint64_t)0x0000FFFF0000FFFF; + x0 |= (x0 << 8); + x1 |= (x1 << 8); + x2 |= (x2 << 8); + x3 |= (x3 << 8); + x0 &= (uint64_t)0x00FF00FF00FF00FF; + x1 &= (uint64_t)0x00FF00FF00FF00FF; + x2 &= (uint64_t)0x00FF00FF00FF00FF; + x3 &= (uint64_t)0x00FF00FF00FF00FF; + *q0 = x0 | (x2 << 8); + *q1 = x1 | (x3 << 8); +} + + +static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) +{ + uint64_t x0, x1, x2, x3; + + x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; + x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; + x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; + x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; + x0 |= (x0 >> 8); + x1 |= (x1 >> 8); + x2 |= (x2 >> 8); + x3 |= (x3 >> 8); + x0 &= (uint64_t)0x0000FFFF0000FFFF; + x1 &= (uint64_t)0x0000FFFF0000FFFF; + x2 &= (uint64_t)0x0000FFFF0000FFFF; + x3 &= (uint64_t)0x0000FFFF0000FFFF; + w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); + w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); + w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); + w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); +} + +static inline void add_round_key(uint64_t *q, const uint64_t *sk) +{ + q[0] ^= sk[0]; + q[1] ^= sk[1]; + q[2] ^= sk[2]; + q[3] ^= sk[3]; + q[4] ^= sk[4]; + q[5] ^= sk[5]; + q[6] ^= sk[6]; + q[7] ^= sk[7]; +} + +static inline void shift_rows(uint64_t *q) +{ + int i; + + for (i = 0; i < 8; i++) { + uint64_t x; + + x = q[i]; + q[i] = (x & (uint64_t)0x000000000000FFFF) + | ((x & (uint64_t)0x00000000FFF00000) >> 4) + | ((x & (uint64_t)0x00000000000F0000) << 12) + | ((x & (uint64_t)0x0000FF0000000000) >> 8) + | ((x & (uint64_t)0x000000FF00000000) << 8) + | ((x & (uint64_t)0xF000000000000000) >> 12) + | ((x & (uint64_t)0x0FFF000000000000) << 4); + } +} + +static inline uint64_t rotr32(uint64_t x) +{ + return (x << 32) | (x >> 32); +} + +static inline void mix_columns(uint64_t *q) +{ + uint64_t q0, q1, q2, q3, q4, q5, q6, q7; + uint64_t r0, r1, r2, r3, r4, r5, r6, r7; + + q0 = q[0]; + q1 = q[1]; + q2 = q[2]; + q3 = q[3]; + q4 = q[4]; + q5 = q[5]; + q6 = q[6]; + q7 = q[7]; + r0 = (q0 >> 16) | (q0 << 48); + r1 = (q1 >> 16) | (q1 << 48); + r2 = (q2 >> 16) | (q2 << 48); + r3 = (q3 >> 16) | (q3 << 48); + r4 = (q4 >> 16) | (q4 << 48); + r5 = (q5 >> 16) | (q5 << 48); + r6 = (q6 >> 16) | (q6 << 48); + r7 = (q7 >> 16) | (q7 << 48); + + q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); + q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); + q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); + q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); + q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); + q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); + q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); + q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); +} + +static void interleave_constant(uint64_t *out, const unsigned char *in) +{ + uint32_t tmp_32_constant[16]; + int i; + + br_range_dec32le(tmp_32_constant, 16, in); + for (i = 0; i < 4; i++) { + br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); + } + br_aes_ct64_ortho(out); +} + +static void interleave_constant32(uint32_t *out, const unsigned char *in) +{ + int i; + for (i = 0; i < 4; i++) { + out[2*i] = br_dec32le(in + 4*i); + out[2*i + 1] = br_dec32le(in + 4*i + 16); + } + br_aes_ct_ortho(out); +} + +void tweak_constants(spx_ctx *ctx) +{ + unsigned char buf[40*16]; + int i; + + /* Use the standard constants to generate tweaked ones. */ + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40*16); + + /* Constants for pk.seed */ + haraka_S(buf, 40*16, ctx->pub_seed, SPX_N, ctx); + for (i = 0; i < 10; i++) { + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32*i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64*i); + } +} + +static void haraka_S_absorb(unsigned char *s, unsigned int r, + const unsigned char *m, unsigned long long mlen, + unsigned char p, const spx_ctx *ctx) +{ + unsigned long long i; + SPX_VLA(uint8_t, t, r); + + while (mlen >= r) { + /* XOR block to state */ + for (i = 0; i < r; ++i) { + s[i] ^= m[i]; + } + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; + } + + for (i = 0; i < r; ++i) { + t[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t[i] = m[i]; + } + t[i] = p; + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { + s[i] ^= t[i]; + } +} + +static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, + unsigned char *s, unsigned int r, + const spx_ctx *ctx) +{ + while (nblocks > 0) { + haraka512_perm(s, s, ctx); + memcpy(h, s, HARAKAS_RATE); + h += r; + nblocks--; + } +} + +void haraka_S_inc_init(uint8_t *s_inc) +{ + size_t i; + + for (i = 0; i < 64; i++) { + s_inc[i] = 0; + } + s_inc[64] = 0; +} + +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) +{ + size_t i; + + /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ + while (mlen + s_inc[64] >= HARAKAS_RATE) { + for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { + /* Take the i'th byte from message + xor with the s_inc[64] + i'th byte of the state */ + s_inc[s_inc[64] + i] ^= m[i]; + } + mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); + m += HARAKAS_RATE - (uint8_t)s_inc[64]; + s_inc[64] = 0; + + haraka512_perm(s_inc, s_inc, ctx); + } + + for (i = 0; i < mlen; i++) { + s_inc[s_inc[64] + i] ^= m[i]; + } + s_inc[64] += (uint8_t)mlen; +} + +void haraka_S_inc_finalize(uint8_t *s_inc) +{ + /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, + so we can always use one more byte for p in the current state. */ + s_inc[s_inc[64]] ^= 0x1F; + s_inc[HARAKAS_RATE - 1] ^= 128; + s_inc[64] = 0; +} + +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) +{ + size_t i; + + /* First consume any bytes we still have sitting around */ + for (i = 0; i < outlen && i < s_inc[64]; i++) { + /* There are s_inc[64] bytes left, so r - s_inc[64] is the first + available byte. We consume from there, i.e., up to r. */ + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + } + out += i; + outlen -= i; + s_inc[64] -= (uint8_t)i; + + /* Then squeeze the remaining necessary blocks */ + while (outlen > 0) { + haraka512_perm(s_inc, s_inc, ctx); + + for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { + out[i] = s_inc[i]; + } + out += i; + outlen -= i; + s_inc[64] = (uint8_t)(HARAKAS_RATE - i); + } +} + +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) +{ + unsigned long long i; + unsigned char s[64]; + unsigned char d[32]; + + for (i = 0; i < 64; i++) { + s[i] = 0; + } + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); + + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); + out += (outlen / 32) * 32; + + if (outlen % 32) { + haraka_S_squeezeblocks(d, 1, s, 32, ctx); + for (i = 0; i < outlen % 32; i++) { + out[i] = d[i]; + } + } +} + +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) +{ + uint32_t w[16]; + uint64_t q[8], tmp_q; + unsigned int i, j; + + br_range_dec32le(w, 16, in); + for (i = 0; i < 4; i++) { + br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); + } + br_aes_ct64_ortho(q); + + /* AES rounds */ + for (i = 0; i < 5; i++) { + for (j = 0; j < 2; j++) { + br_aes_ct64_bitslice_Sbox(q); + shift_rows(q); + mix_columns(q); + add_round_key(q, ctx->tweaked512_rc64[2*i + j]); + } + /* Mix states */ + for (j = 0; j < 8; j++) { + tmp_q = q[j]; + q[j] = (tmp_q & 0x0001000100010001) << 5 | + (tmp_q & 0x0002000200020002) << 12 | + (tmp_q & 0x0004000400040004) >> 1 | + (tmp_q & 0x0008000800080008) << 6 | + (tmp_q & 0x0020002000200020) << 9 | + (tmp_q & 0x0040004000400040) >> 4 | + (tmp_q & 0x0080008000800080) << 3 | + (tmp_q & 0x2100210021002100) >> 5 | + (tmp_q & 0x0210021002100210) << 2 | + (tmp_q & 0x0800080008000800) << 4 | + (tmp_q & 0x1000100010001000) >> 12 | + (tmp_q & 0x4000400040004000) >> 10 | + (tmp_q & 0x8400840084008400) >> 3; + } + } + + br_aes_ct64_ortho(q); + for (i = 0; i < 4; i ++) { + br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); + } + br_range_enc32le(out, w, 16); +} + +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) +{ + int i; + + unsigned char buf[64]; + + haraka512_perm(buf, in, ctx); + /* Feed-forward */ + for (i = 0; i < 64; i++) { + buf[i] = buf[i] ^ in[i]; + } + + /* Truncated */ + memcpy(out, buf + 8, 8); + memcpy(out + 8, buf + 24, 8); + memcpy(out + 16, buf + 32, 8); + memcpy(out + 24, buf + 48, 8); +} + + +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) +{ + uint32_t q[8], tmp_q; + int i, j; + + for (i = 0; i < 4; i++) { + q[2*i] = br_dec32le(in + 4*i); + q[2*i + 1] = br_dec32le(in + 4*i + 16); + } + br_aes_ct_ortho(q); + + /* AES rounds */ + for (i = 0; i < 5; i++) { + for (j = 0; j < 2; j++) { + br_aes_ct_bitslice_Sbox(q); + shift_rows32(q); + mix_columns32(q); + add_round_key32(q, ctx->tweaked256_rc32[2*i + j]); + } + + /* Mix states */ + for (j = 0; j < 8; j++) { + tmp_q = q[j]; + q[j] = (tmp_q & 0x81818181) | + (tmp_q & 0x02020202) << 1 | + (tmp_q & 0x04040404) << 2 | + (tmp_q & 0x08080808) << 3 | + (tmp_q & 0x10101010) >> 3 | + (tmp_q & 0x20202020) >> 2 | + (tmp_q & 0x40404040) >> 1; + } + } + + br_aes_ct_ortho(q); + for (i = 0; i < 4; i++) { + br_enc32le(out + 4*i, q[2*i]); + br_enc32le(out + 4*i + 16, q[2*i + 1]); + } + + for (i = 0; i < 32; i++) { + out[i] ^= in[i]; + } +} diff --git a/ref/haraka.h b/ref/haraka.h new file mode 100644 index 0000000..7cd311c --- /dev/null +++ b/ref/haraka.h @@ -0,0 +1,41 @@ +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H + +#include "context.h" + +/* Tweak constants with seed */ +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); + +/* Haraka Sponge */ +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation to in. */ +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 */ +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 */ +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/ref/haraka_offsets.h b/ref/haraka_offsets.h new file mode 100644 index 0000000..6afa5f8 --- /dev/null +++ b/ref/haraka_offsets.h @@ -0,0 +1,20 @@ +#if !defined( HARAKA_OFFSETS_H_ ) +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR 20 /* The start of the 4 byte field used to specify the key pair address */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/ref/hash.h b/ref/hash.h new file mode 100644 index 0000000..b141f09 --- /dev/null +++ b/ref/hash.h @@ -0,0 +1,27 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include "context.h" +#include "params.h" + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, unsigned long long mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, unsigned long long mlen, + const spx_ctx *ctx); + +#endif diff --git a/ref/hash_haraka.c b/ref/hash_haraka.c new file mode 100644 index 0000000..0c73525 --- /dev/null +++ b/ref/hash_haraka.c @@ -0,0 +1,96 @@ +#include +#include + +#include "address.h" +#include "utils.h" +#include "params.h" + +#include "haraka.h" +#include "hash.h" + +void initialize_hash_function(spx_ctx* ctx) +{ + tweak_constants(ctx); +} + +/* + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) +{ + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ + unsigned char outbuf[32]; + unsigned char buf[64] = {0}; + + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char* sk_prf, + const unsigned char *optrand, + const unsigned char *m, unsigned long long mlen, + const spx_ctx *ctx) +{ + uint8_t s_inc[65]; + + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, unsigned long long mlen, + const spx_ctx *ctx) +{ +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + uint8_t s_inc[65]; + + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + +#if SPX_TREE_BITS > 64 + #error For given height and depth, 64 bits cannot represent all subtrees +#endif + + if (SPX_D == 1) { + *tree = 0; + } else { + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + } + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/ref/hash_sha2.c b/ref/hash_sha2.c new file mode 100644 index 0000000..67098e6 --- /dev/null +++ b/ref/hash_sha2.c @@ -0,0 +1,197 @@ +#include +#include + +#include "address.h" +#include "utils.h" +#include "params.h" +#include "hash.h" +#include "sha2.h" + +#if SPX_N >= 24 +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#else +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES +#define shaX_inc_init sha256_inc_init +#define shaX_inc_blocks sha256_inc_blocks +#define shaX_inc_finalize sha256_inc_finalize +#define shaX sha256 +#define mgf1_X mgf1_256 +#endif + + +/* For SHA, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) +{ + seed_state(ctx); +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) +{ + uint8_t sha2_state[40]; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + memcpy(sha2_state, ctx->state_seeded, 40 * sizeof(uint8_t)); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, unsigned long long mlen, + const spx_ctx *ctx) +{ + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + uint8_t state[8 + SPX_SHAX_OUTPUT_BYTES]; + int i; + +#if SPX_N > SPX_SHAX_BLOCK_BYTES + #error "Currently only supports SPX_N of at most SPX_SHAX_BLOCK_BYTES" +#endif + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(state); + shaX_inc_blocks(state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, unsigned long long mlen, + const spx_ctx *ctx) +{ + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2*SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#if (SPX_SHAX_BLOCK_BYTES & (SPX_SHAX_BLOCK_BYTES-1)) != 0 + #error "Assumes that SPX_SHAX_BLOCK_BYTES is a power of 2" +#endif +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + uint8_t state[8 + SPX_SHAX_OUTPUT_BYTES]; + + shaX_inc_init(state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2*SPX_N, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2*SPX_N, state, m, mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2*SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + +#if SPX_TREE_BITS > 64 + #error For given height and depth, 64 bits cannot represent all subtrees +#endif + + if (SPX_D == 1) { + *tree = 0; + } else { + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + } + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/ref/hash_shake.c b/ref/hash_shake.c new file mode 100644 index 0000000..f0372bf --- /dev/null +++ b/ref/hash_shake.c @@ -0,0 +1,97 @@ +#include +#include + +#include "address.h" +#include "utils.h" +#include "params.h" +#include "hash.h" +#include "fips202.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx* ctx) +{ + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) +{ + unsigned char buf[2*SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2*SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, unsigned long long mlen, + const spx_ctx *ctx) +{ + (void)ctx; + uint64_t s_inc[26]; + + shake256_inc_init(s_inc); + shake256_inc_absorb(s_inc, sk_prf, SPX_N); + shake256_inc_absorb(s_inc, optrand, SPX_N); + shake256_inc_absorb(s_inc, m, mlen); + shake256_inc_finalize(s_inc); + shake256_inc_squeeze(R, SPX_N, s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, unsigned long long mlen, + const spx_ctx *ctx) +{ + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + uint64_t s_inc[26]; + + shake256_inc_init(s_inc); + shake256_inc_absorb(s_inc, R, SPX_N); + shake256_inc_absorb(s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(s_inc, m, mlen); + shake256_inc_finalize(s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + +#if SPX_TREE_BITS > 64 + #error For given height and depth, 64 bits cannot represent all subtrees +#endif + + if (SPX_D == 1) { + *tree = 0; + } else { + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + } + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/ref/merkle.c b/ref/merkle.c new file mode 100644 index 0000000..414f468 --- /dev/null +++ b/ref/merkle.c @@ -0,0 +1,61 @@ +#include +#include + +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" +#include "merkle.h" +#include "address.h" +#include "params.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) +{ + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) +{ + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/ref/merkle.h b/ref/merkle.h new file mode 100644 index 0000000..9ac2759 --- /dev/null +++ b/ref/merkle.h @@ -0,0 +1,18 @@ +#if !defined( MERKLE_H_ ) +#define MERKLE_H_ + +#include + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx* ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx* ctx); + +#endif /* MERKLE_H_ */ diff --git a/ref/params.h b/ref/params.h new file mode 100644 index 0000000..1d7f9c9 --- /dev/null +++ b/ref/params.h @@ -0,0 +1,5 @@ +#define str(s) #s +#define xstr(s) str(s) + +#include xstr(params/params-PARAMS.h) + diff --git a/ref/params/params-sphincs-haraka-128f.h b/ref/params/params-sphincs-haraka-128f.h new file mode 100644 index 0000000..a9bb1cf --- /dev/null +++ b/ref/params/params-sphincs-haraka-128f.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../haraka_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-haraka-128s.h b/ref/params/params-sphincs-haraka-128s.h new file mode 100644 index 0000000..73372ee --- /dev/null +++ b/ref/params/params-sphincs-haraka-128s.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../haraka_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-haraka-192f.h b/ref/params/params-sphincs-haraka-192f.h new file mode 100644 index 0000000..9eb356a --- /dev/null +++ b/ref/params/params-sphincs-haraka-192f.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../haraka_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-haraka-192s.h b/ref/params/params-sphincs-haraka-192s.h new file mode 100644 index 0000000..00b6b70 --- /dev/null +++ b/ref/params/params-sphincs-haraka-192s.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../haraka_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-haraka-256f.h b/ref/params/params-sphincs-haraka-256f.h new file mode 100644 index 0000000..7491b66 --- /dev/null +++ b/ref/params/params-sphincs-haraka-256f.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../haraka_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-haraka-256s.h b/ref/params/params-sphincs-haraka-256s.h new file mode 100644 index 0000000..6ef3a5c --- /dev/null +++ b/ref/params/params-sphincs-haraka-256s.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../haraka_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-sha2-128f.h b/ref/params/params-sphincs-sha2-128f.h new file mode 100644 index 0000000..3f7a60f --- /dev/null +++ b/ref/params/params-sphincs-sha2-128f.h @@ -0,0 +1,85 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../sha2_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-sha2-128s.h b/ref/params/params-sphincs-sha2-128s.h new file mode 100644 index 0000000..8ef8608 --- /dev/null +++ b/ref/params/params-sphincs-sha2-128s.h @@ -0,0 +1,85 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../sha2_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-sha2-192f.h b/ref/params/params-sphincs-sha2-192f.h new file mode 100644 index 0000000..d4d98a2 --- /dev/null +++ b/ref/params/params-sphincs-sha2-192f.h @@ -0,0 +1,85 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../sha2_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-sha2-192s.h b/ref/params/params-sphincs-sha2-192s.h new file mode 100644 index 0000000..0070e59 --- /dev/null +++ b/ref/params/params-sphincs-sha2-192s.h @@ -0,0 +1,85 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../sha2_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-sha2-256f.h b/ref/params/params-sphincs-sha2-256f.h new file mode 100644 index 0000000..53c5bef --- /dev/null +++ b/ref/params/params-sphincs-sha2-256f.h @@ -0,0 +1,85 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../sha2_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-sha2-256s.h b/ref/params/params-sphincs-sha2-256s.h new file mode 100644 index 0000000..10c3663 --- /dev/null +++ b/ref/params/params-sphincs-sha2-256s.h @@ -0,0 +1,85 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../sha2_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-shake-128f.h b/ref/params/params-sphincs-shake-128f.h new file mode 100644 index 0000000..8f77692 --- /dev/null +++ b/ref/params/params-sphincs-shake-128f.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../shake_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-shake-128s.h b/ref/params/params-sphincs-shake-128s.h new file mode 100644 index 0000000..a4d1e13 --- /dev/null +++ b/ref/params/params-sphincs-shake-128s.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../shake_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-shake-192f.h b/ref/params/params-sphincs-shake-192f.h new file mode 100644 index 0000000..b1e73d1 --- /dev/null +++ b/ref/params/params-sphincs-shake-192f.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../shake_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-shake-192s.h b/ref/params/params-sphincs-shake-192s.h new file mode 100644 index 0000000..0882e1c --- /dev/null +++ b/ref/params/params-sphincs-shake-192s.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../shake_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-shake-256f.h b/ref/params/params-sphincs-shake-256f.h new file mode 100644 index 0000000..e301c28 --- /dev/null +++ b/ref/params/params-sphincs-shake-256f.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../shake_offsets.h" + +#endif diff --git a/ref/params/params-sphincs-shake-256s.h b/ref/params/params-sphincs-shake-256s.h new file mode 100644 index 0000000..0a96894 --- /dev/null +++ b/ref/params/params-sphincs-shake-256s.h @@ -0,0 +1,80 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) SPX_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#if SPX_WOTS_W == 256 + #define SPX_WOTS_LOGW 8 +#elif SPX_WOTS_W == 16 + #define SPX_WOTS_LOGW 4 +#else + #error SPX_WOTS_W assumed 16 or 256 +#endif + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#if SPX_WOTS_W == 256 + #if SPX_N <= 1 + #define SPX_WOTS_LEN2 1 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 2 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#elif SPX_WOTS_W == 16 + #if SPX_N <= 8 + #define SPX_WOTS_LEN2 2 + #elif SPX_N <= 136 + #define SPX_WOTS_LEN2 3 + #elif SPX_N <= 256 + #define SPX_WOTS_LEN2 4 + #else + #error Did not precompute SPX_WOTS_LEN2 for n outside {2, .., 256} + #endif +#endif + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT + #error SPX_D should always divide SPX_FULL_HEIGHT +#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "../shake_offsets.h" + +#endif diff --git a/ref/randombytes.c b/ref/randombytes.c new file mode 100644 index 0000000..cfbca17 --- /dev/null +++ b/ref/randombytes.c @@ -0,0 +1,43 @@ +/* +This code was taken from the SPHINCS reference implementation and is public domain. +*/ + +#include +#include + +#include "randombytes.h" + +static int fd = -1; + +void randombytes(unsigned char *x, unsigned long long xlen) +{ + unsigned long long i; + + if (fd == -1) { + for (;;) { + fd = open("/dev/urandom", O_RDONLY); + if (fd != -1) { + break; + } + sleep(1); + } + } + + while (xlen > 0) { + if (xlen < 1048576) { + i = xlen; + } + else { + i = 1048576; + } + + i = (unsigned long long)read(fd, x, i); + if (i < 1) { + sleep(1); + continue; + } + + x += i; + xlen -= i; + } +} diff --git a/ref/randombytes.h b/ref/randombytes.h new file mode 100644 index 0000000..671c1b1 --- /dev/null +++ b/ref/randombytes.h @@ -0,0 +1,6 @@ +#ifndef SPX_RANDOMBYTES_H +#define SPX_RANDOMBYTES_H + +extern void randombytes(unsigned char * x,unsigned long long xlen); + +#endif diff --git a/ref/rng.c b/ref/rng.c new file mode 100644 index 0000000..36f5b27 --- /dev/null +++ b/ref/rng.c @@ -0,0 +1,218 @@ +// +// rng.c +// +// Created by Bassham, Lawrence E (Fed) on 8/29/17. +// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. +// + +#include +#include "rng.h" +#include +#include +#include + +AES256_CTR_DRBG_struct DRBG_ctx; + +void AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer); + +/* + seedexpander_init() + ctx - stores the current state of an instance of the seed expander + seed - a 32 byte random value + diversifier - an 8 byte diversifier + maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier + */ +int +seedexpander_init(AES_XOF_struct *ctx, + unsigned char *seed, + unsigned char *diversifier, + unsigned long maxlen) +{ + if ( maxlen >= 0x100000000 ) + return RNG_BAD_MAXLEN; + + ctx->length_remaining = maxlen; + + memcpy(ctx->key, seed, 32); + + memcpy(ctx->ctr, diversifier, 8); + ctx->ctr[11] = (unsigned char)(maxlen % 256); + maxlen >>= 8; + ctx->ctr[10] = (unsigned char)(maxlen % 256); + maxlen >>= 8; + ctx->ctr[9] = (unsigned char)(maxlen % 256); + maxlen >>= 8; + ctx->ctr[8] = (unsigned char)(maxlen % 256); + memset(ctx->ctr+12, 0x00, 4); + + ctx->buffer_pos = 16; + memset(ctx->buffer, 0x00, 16); + + return RNG_SUCCESS; +} + +/* + seedexpander() + ctx - stores the current state of an instance of the seed expander + x - returns the XOF data + xlen - number of bytes to return + */ +int +seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen) +{ + unsigned long offset; + + if ( x == NULL ) + return RNG_BAD_OUTBUF; + if ( xlen >= ctx->length_remaining ) + return RNG_BAD_REQ_LEN; + + ctx->length_remaining -= xlen; + + offset = 0; + while ( xlen > 0 ) { + if ( xlen <= (16-ctx->buffer_pos) ) { // buffer has what we need + memcpy(x+offset, ctx->buffer+ctx->buffer_pos, xlen); + ctx->buffer_pos += xlen; + + return RNG_SUCCESS; + } + + // take what's in the buffer + memcpy(x+offset, ctx->buffer+ctx->buffer_pos, 16-ctx->buffer_pos); + xlen -= 16-ctx->buffer_pos; + offset += 16-ctx->buffer_pos; + + AES256_ECB(ctx->key, ctx->ctr, ctx->buffer); + ctx->buffer_pos = 0; + + //increment the counter + for (int i=15; i>=12; i--) { + if ( ctx->ctr[i] == 0xff ) + ctx->ctr[i] = 0x00; + else { + ctx->ctr[i]++; + break; + } + } + + } + + return RNG_SUCCESS; +} + + +static void handleErrors(void) +{ + ERR_print_errors_fp(stderr); + abort(); +} + +// Use whatever AES implementation you have. This uses AES from openSSL library +// key - 256-bit AES key +// ctr - a 128-bit plaintext value +// buffer - a 128-bit ciphertext value +void +AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer) +{ + EVP_CIPHER_CTX *ctx; + + int len; + + /* Create and initialise the context */ + if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); + + if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL)) + handleErrors(); + + if(1 != EVP_EncryptUpdate(ctx, buffer, &len, ctr, 16)) + handleErrors(); + + /* Clean up */ + EVP_CIPHER_CTX_free(ctx); +} + +void +randombytes_init(unsigned char *entropy_input, + unsigned char *personalization_string) +{ + unsigned char seed_material[48]; + + memcpy(seed_material, entropy_input, 48); + if (personalization_string) + for (int i=0; i<48; i++) + seed_material[i] ^= personalization_string[i]; + memset(DRBG_ctx.Key, 0x00, 32); + memset(DRBG_ctx.V, 0x00, 16); + AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V); + DRBG_ctx.reseed_counter = 1; +} + +int +randombytes(unsigned char *x, unsigned long long xlen) +{ + unsigned char block[16]; + int i = 0; + + while ( xlen > 0 ) { + //increment V + for (int j=15; j>=0; j--) { + if ( DRBG_ctx.V[j] == 0xff ) + DRBG_ctx.V[j] = 0x00; + else { + DRBG_ctx.V[j]++; + break; + } + } + AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block); + if ( xlen > 15 ) { + memcpy(x+i, block, 16); + i += 16; + xlen -= 16; + } + else { + memcpy(x+i, block, xlen); + xlen = 0; + } + } + AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V); + DRBG_ctx.reseed_counter++; + + return RNG_SUCCESS; +} + +void +AES256_CTR_DRBG_Update(unsigned char *provided_data, + unsigned char *Key, + unsigned char *V) +{ + unsigned char temp[48]; + + for (int i=0; i<3; i++) { + //increment V + for (int j=15; j>=0; j--) { + if ( V[j] == 0xff ) + V[j] = 0x00; + else { + V[j]++; + break; + } + } + + AES256_ECB(Key, V, temp+16*i); + } + if ( provided_data != NULL ) + for (int i=0; i<48; i++) + temp[i] ^= provided_data[i]; + memcpy(Key, temp, 32); + memcpy(V, temp+32, 16); +} + + + + + + + + + diff --git a/ref/rng.h b/ref/rng.h new file mode 100644 index 0000000..c4f1c60 --- /dev/null +++ b/ref/rng.h @@ -0,0 +1,54 @@ +// +// rng.h +// +// Created by Bassham, Lawrence E (Fed) on 8/29/17. +// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. +// + +#ifndef rng_h +#define rng_h + +#include + +#define RNG_SUCCESS 0 +#define RNG_BAD_MAXLEN -1 +#define RNG_BAD_OUTBUF -2 +#define RNG_BAD_REQ_LEN -3 + +typedef struct { + unsigned char buffer[16]; + unsigned long buffer_pos; + unsigned long length_remaining; + unsigned char key[32]; + unsigned char ctr[16]; +} AES_XOF_struct; + +typedef struct { + unsigned char Key[32]; + unsigned char V[16]; + int reseed_counter; +} AES256_CTR_DRBG_struct; + + +void +AES256_CTR_DRBG_Update(unsigned char *provided_data, + unsigned char *Key, + unsigned char *V); + +int +seedexpander_init(AES_XOF_struct *ctx, + unsigned char *seed, + unsigned char *diversifier, + unsigned long maxlen); + +int +seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen); + +void +randombytes_init(unsigned char *entropy_input, + unsigned char *personalization_string); + +int +randombytes(unsigned char *x, unsigned long long xlen); + +#endif /* rng_h */ diff --git a/ref/sha2.c b/ref/sha2.c new file mode 100644 index 0000000..ef73047 --- /dev/null +++ b/ref/sha2.c @@ -0,0 +1,700 @@ +/* Based on the public domain implementation in + * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html + * by D. J. Bernstein */ + +#include +#include +#include + +#include "utils.h" +#include "sha2.h" + +static uint32_t load_bigendian_32(const uint8_t *x) { + return (uint32_t)(x[3]) | (((uint32_t)(x[2])) << 8) | + (((uint32_t)(x[1])) << 16) | (((uint32_t)(x[0])) << 24); +} + +static uint64_t load_bigendian_64(const uint8_t *x) { + return (uint64_t)(x[7]) | (((uint64_t)(x[6])) << 8) | + (((uint64_t)(x[5])) << 16) | (((uint64_t)(x[4])) << 24) | + (((uint64_t)(x[3])) << 32) | (((uint64_t)(x[2])) << 40) | + (((uint64_t)(x[1])) << 48) | (((uint64_t)(x[0])) << 56); +} + +static void store_bigendian_32(uint8_t *x, uint64_t u) { + x[3] = (uint8_t) u; + u >>= 8; + x[2] = (uint8_t) u; + u >>= 8; + x[1] = (uint8_t) u; + u >>= 8; + x[0] = (uint8_t) u; +} + +static void store_bigendian_64(uint8_t *x, uint64_t u) { + x[7] = (uint8_t) u; + u >>= 8; + x[6] = (uint8_t) u; + u >>= 8; + x[5] = (uint8_t) u; + u >>= 8; + x[4] = (uint8_t) u; + u >>= 8; + x[3] = (uint8_t) u; + u >>= 8; + x[2] = (uint8_t) u; + u >>= 8; + x[1] = (uint8_t) u; + u >>= 8; + x[0] = (uint8_t) u; +} + +#define SHR(x, c) ((x) >> (c)) +#define ROTR_32(x, c) (((x) >> (c)) | ((x) << (32 - (c)))) +#define ROTR_64(x,c) (((x) >> (c)) | ((x) << (64 - (c)))) + +#define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) +#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#define Sigma0_32(x) (ROTR_32(x, 2) ^ ROTR_32(x,13) ^ ROTR_32(x,22)) +#define Sigma1_32(x) (ROTR_32(x, 6) ^ ROTR_32(x,11) ^ ROTR_32(x,25)) +#define sigma0_32(x) (ROTR_32(x, 7) ^ ROTR_32(x,18) ^ SHR(x, 3)) +#define sigma1_32(x) (ROTR_32(x,17) ^ ROTR_32(x,19) ^ SHR(x,10)) + +#define Sigma0_64(x) (ROTR_64(x,28) ^ ROTR_64(x,34) ^ ROTR_64(x,39)) +#define Sigma1_64(x) (ROTR_64(x,14) ^ ROTR_64(x,18) ^ ROTR_64(x,41)) +#define sigma0_64(x) (ROTR_64(x, 1) ^ ROTR_64(x, 8) ^ SHR(x,7)) +#define sigma1_64(x) (ROTR_64(x,19) ^ ROTR_64(x,61) ^ SHR(x,6)) + +#define M_32(w0, w14, w9, w1) w0 = sigma1_32(w14) + (w9) + sigma0_32(w1) + (w0); +#define M_64(w0, w14, w9, w1) w0 = sigma1_64(w14) + (w9) + sigma0_64(w1) + (w0); + +#define EXPAND_32 \ + M_32(w0, w14, w9, w1) \ + M_32(w1, w15, w10, w2) \ + M_32(w2, w0, w11, w3) \ + M_32(w3, w1, w12, w4) \ + M_32(w4, w2, w13, w5) \ + M_32(w5, w3, w14, w6) \ + M_32(w6, w4, w15, w7) \ + M_32(w7, w5, w0, w8) \ + M_32(w8, w6, w1, w9) \ + M_32(w9, w7, w2, w10) \ + M_32(w10, w8, w3, w11) \ + M_32(w11, w9, w4, w12) \ + M_32(w12, w10, w5, w13) \ + M_32(w13, w11, w6, w14) \ + M_32(w14, w12, w7, w15) \ + M_32(w15, w13, w8, w0) + +#define EXPAND_64 \ + M_64(w0 ,w14,w9 ,w1 ) \ + M_64(w1 ,w15,w10,w2 ) \ + M_64(w2 ,w0 ,w11,w3 ) \ + M_64(w3 ,w1 ,w12,w4 ) \ + M_64(w4 ,w2 ,w13,w5 ) \ + M_64(w5 ,w3 ,w14,w6 ) \ + M_64(w6 ,w4 ,w15,w7 ) \ + M_64(w7 ,w5 ,w0 ,w8 ) \ + M_64(w8 ,w6 ,w1 ,w9 ) \ + M_64(w9 ,w7 ,w2 ,w10) \ + M_64(w10,w8 ,w3 ,w11) \ + M_64(w11,w9 ,w4 ,w12) \ + M_64(w12,w10,w5 ,w13) \ + M_64(w13,w11,w6 ,w14) \ + M_64(w14,w12,w7 ,w15) \ + M_64(w15,w13,w8 ,w0 ) + +#define F_32(w, k) \ + T1 = h + Sigma1_32(e) + Ch(e, f, g) + (k) + (w); \ + T2 = Sigma0_32(a) + Maj(a, b, c); \ + h = g; \ + g = f; \ + f = e; \ + e = d + T1; \ + d = c; \ + c = b; \ + b = a; \ + a = T1 + T2; + +#define F_64(w,k) \ + T1 = h + Sigma1_64(e) + Ch(e,f,g) + k + w; \ + T2 = Sigma0_64(a) + Maj(a,b,c); \ + h = g; \ + g = f; \ + f = e; \ + e = d + T1; \ + d = c; \ + c = b; \ + b = a; \ + a = T1 + T2; + +static size_t crypto_hashblocks_sha256(uint8_t *statebytes, + const uint8_t *in, size_t inlen) { + uint32_t state[8]; + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; + uint32_t e; + uint32_t f; + uint32_t g; + uint32_t h; + uint32_t T1; + uint32_t T2; + + a = load_bigendian_32(statebytes + 0); + state[0] = a; + b = load_bigendian_32(statebytes + 4); + state[1] = b; + c = load_bigendian_32(statebytes + 8); + state[2] = c; + d = load_bigendian_32(statebytes + 12); + state[3] = d; + e = load_bigendian_32(statebytes + 16); + state[4] = e; + f = load_bigendian_32(statebytes + 20); + state[5] = f; + g = load_bigendian_32(statebytes + 24); + state[6] = g; + h = load_bigendian_32(statebytes + 28); + state[7] = h; + + while (inlen >= 64) { + uint32_t w0 = load_bigendian_32(in + 0); + uint32_t w1 = load_bigendian_32(in + 4); + uint32_t w2 = load_bigendian_32(in + 8); + uint32_t w3 = load_bigendian_32(in + 12); + uint32_t w4 = load_bigendian_32(in + 16); + uint32_t w5 = load_bigendian_32(in + 20); + uint32_t w6 = load_bigendian_32(in + 24); + uint32_t w7 = load_bigendian_32(in + 28); + uint32_t w8 = load_bigendian_32(in + 32); + uint32_t w9 = load_bigendian_32(in + 36); + uint32_t w10 = load_bigendian_32(in + 40); + uint32_t w11 = load_bigendian_32(in + 44); + uint32_t w12 = load_bigendian_32(in + 48); + uint32_t w13 = load_bigendian_32(in + 52); + uint32_t w14 = load_bigendian_32(in + 56); + uint32_t w15 = load_bigendian_32(in + 60); + + F_32(w0, 0x428a2f98) + F_32(w1, 0x71374491) + F_32(w2, 0xb5c0fbcf) + F_32(w3, 0xe9b5dba5) + F_32(w4, 0x3956c25b) + F_32(w5, 0x59f111f1) + F_32(w6, 0x923f82a4) + F_32(w7, 0xab1c5ed5) + F_32(w8, 0xd807aa98) + F_32(w9, 0x12835b01) + F_32(w10, 0x243185be) + F_32(w11, 0x550c7dc3) + F_32(w12, 0x72be5d74) + F_32(w13, 0x80deb1fe) + F_32(w14, 0x9bdc06a7) + F_32(w15, 0xc19bf174) + + EXPAND_32 + + F_32(w0, 0xe49b69c1) + F_32(w1, 0xefbe4786) + F_32(w2, 0x0fc19dc6) + F_32(w3, 0x240ca1cc) + F_32(w4, 0x2de92c6f) + F_32(w5, 0x4a7484aa) + F_32(w6, 0x5cb0a9dc) + F_32(w7, 0x76f988da) + F_32(w8, 0x983e5152) + F_32(w9, 0xa831c66d) + F_32(w10, 0xb00327c8) + F_32(w11, 0xbf597fc7) + F_32(w12, 0xc6e00bf3) + F_32(w13, 0xd5a79147) + F_32(w14, 0x06ca6351) + F_32(w15, 0x14292967) + + EXPAND_32 + + F_32(w0, 0x27b70a85) + F_32(w1, 0x2e1b2138) + F_32(w2, 0x4d2c6dfc) + F_32(w3, 0x53380d13) + F_32(w4, 0x650a7354) + F_32(w5, 0x766a0abb) + F_32(w6, 0x81c2c92e) + F_32(w7, 0x92722c85) + F_32(w8, 0xa2bfe8a1) + F_32(w9, 0xa81a664b) + F_32(w10, 0xc24b8b70) + F_32(w11, 0xc76c51a3) + F_32(w12, 0xd192e819) + F_32(w13, 0xd6990624) + F_32(w14, 0xf40e3585) + F_32(w15, 0x106aa070) + + EXPAND_32 + + F_32(w0, 0x19a4c116) + F_32(w1, 0x1e376c08) + F_32(w2, 0x2748774c) + F_32(w3, 0x34b0bcb5) + F_32(w4, 0x391c0cb3) + F_32(w5, 0x4ed8aa4a) + F_32(w6, 0x5b9cca4f) + F_32(w7, 0x682e6ff3) + F_32(w8, 0x748f82ee) + F_32(w9, 0x78a5636f) + F_32(w10, 0x84c87814) + F_32(w11, 0x8cc70208) + F_32(w12, 0x90befffa) + F_32(w13, 0xa4506ceb) + F_32(w14, 0xbef9a3f7) + F_32(w15, 0xc67178f2) + + a += state[0]; + b += state[1]; + c += state[2]; + d += state[3]; + e += state[4]; + f += state[5]; + g += state[6]; + h += state[7]; + + state[0] = a; + state[1] = b; + state[2] = c; + state[3] = d; + state[4] = e; + state[5] = f; + state[6] = g; + state[7] = h; + + in += 64; + inlen -= 64; + } + + store_bigendian_32(statebytes + 0, state[0]); + store_bigendian_32(statebytes + 4, state[1]); + store_bigendian_32(statebytes + 8, state[2]); + store_bigendian_32(statebytes + 12, state[3]); + store_bigendian_32(statebytes + 16, state[4]); + store_bigendian_32(statebytes + 20, state[5]); + store_bigendian_32(statebytes + 24, state[6]); + store_bigendian_32(statebytes + 28, state[7]); + + return inlen; +} + +static int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen) +{ + uint64_t state[8]; + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t d; + uint64_t e; + uint64_t f; + uint64_t g; + uint64_t h; + uint64_t T1; + uint64_t T2; + + a = load_bigendian_64(statebytes + 0); state[0] = a; + b = load_bigendian_64(statebytes + 8); state[1] = b; + c = load_bigendian_64(statebytes + 16); state[2] = c; + d = load_bigendian_64(statebytes + 24); state[3] = d; + e = load_bigendian_64(statebytes + 32); state[4] = e; + f = load_bigendian_64(statebytes + 40); state[5] = f; + g = load_bigendian_64(statebytes + 48); state[6] = g; + h = load_bigendian_64(statebytes + 56); state[7] = h; + + while (inlen >= 128) { + uint64_t w0 = load_bigendian_64(in + 0); + uint64_t w1 = load_bigendian_64(in + 8); + uint64_t w2 = load_bigendian_64(in + 16); + uint64_t w3 = load_bigendian_64(in + 24); + uint64_t w4 = load_bigendian_64(in + 32); + uint64_t w5 = load_bigendian_64(in + 40); + uint64_t w6 = load_bigendian_64(in + 48); + uint64_t w7 = load_bigendian_64(in + 56); + uint64_t w8 = load_bigendian_64(in + 64); + uint64_t w9 = load_bigendian_64(in + 72); + uint64_t w10 = load_bigendian_64(in + 80); + uint64_t w11 = load_bigendian_64(in + 88); + uint64_t w12 = load_bigendian_64(in + 96); + uint64_t w13 = load_bigendian_64(in + 104); + uint64_t w14 = load_bigendian_64(in + 112); + uint64_t w15 = load_bigendian_64(in + 120); + + F_64(w0 ,0x428a2f98d728ae22ULL) + F_64(w1 ,0x7137449123ef65cdULL) + F_64(w2 ,0xb5c0fbcfec4d3b2fULL) + F_64(w3 ,0xe9b5dba58189dbbcULL) + F_64(w4 ,0x3956c25bf348b538ULL) + F_64(w5 ,0x59f111f1b605d019ULL) + F_64(w6 ,0x923f82a4af194f9bULL) + F_64(w7 ,0xab1c5ed5da6d8118ULL) + F_64(w8 ,0xd807aa98a3030242ULL) + F_64(w9 ,0x12835b0145706fbeULL) + F_64(w10,0x243185be4ee4b28cULL) + F_64(w11,0x550c7dc3d5ffb4e2ULL) + F_64(w12,0x72be5d74f27b896fULL) + F_64(w13,0x80deb1fe3b1696b1ULL) + F_64(w14,0x9bdc06a725c71235ULL) + F_64(w15,0xc19bf174cf692694ULL) + + EXPAND_64 + + F_64(w0 ,0xe49b69c19ef14ad2ULL) + F_64(w1 ,0xefbe4786384f25e3ULL) + F_64(w2 ,0x0fc19dc68b8cd5b5ULL) + F_64(w3 ,0x240ca1cc77ac9c65ULL) + F_64(w4 ,0x2de92c6f592b0275ULL) + F_64(w5 ,0x4a7484aa6ea6e483ULL) + F_64(w6 ,0x5cb0a9dcbd41fbd4ULL) + F_64(w7 ,0x76f988da831153b5ULL) + F_64(w8 ,0x983e5152ee66dfabULL) + F_64(w9 ,0xa831c66d2db43210ULL) + F_64(w10,0xb00327c898fb213fULL) + F_64(w11,0xbf597fc7beef0ee4ULL) + F_64(w12,0xc6e00bf33da88fc2ULL) + F_64(w13,0xd5a79147930aa725ULL) + F_64(w14,0x06ca6351e003826fULL) + F_64(w15,0x142929670a0e6e70ULL) + + EXPAND_64 + + F_64(w0 ,0x27b70a8546d22ffcULL) + F_64(w1 ,0x2e1b21385c26c926ULL) + F_64(w2 ,0x4d2c6dfc5ac42aedULL) + F_64(w3 ,0x53380d139d95b3dfULL) + F_64(w4 ,0x650a73548baf63deULL) + F_64(w5 ,0x766a0abb3c77b2a8ULL) + F_64(w6 ,0x81c2c92e47edaee6ULL) + F_64(w7 ,0x92722c851482353bULL) + F_64(w8 ,0xa2bfe8a14cf10364ULL) + F_64(w9 ,0xa81a664bbc423001ULL) + F_64(w10,0xc24b8b70d0f89791ULL) + F_64(w11,0xc76c51a30654be30ULL) + F_64(w12,0xd192e819d6ef5218ULL) + F_64(w13,0xd69906245565a910ULL) + F_64(w14,0xf40e35855771202aULL) + F_64(w15,0x106aa07032bbd1b8ULL) + + EXPAND_64 + + F_64(w0 ,0x19a4c116b8d2d0c8ULL) + F_64(w1 ,0x1e376c085141ab53ULL) + F_64(w2 ,0x2748774cdf8eeb99ULL) + F_64(w3 ,0x34b0bcb5e19b48a8ULL) + F_64(w4 ,0x391c0cb3c5c95a63ULL) + F_64(w5 ,0x4ed8aa4ae3418acbULL) + F_64(w6 ,0x5b9cca4f7763e373ULL) + F_64(w7 ,0x682e6ff3d6b2b8a3ULL) + F_64(w8 ,0x748f82ee5defb2fcULL) + F_64(w9 ,0x78a5636f43172f60ULL) + F_64(w10,0x84c87814a1f0ab72ULL) + F_64(w11,0x8cc702081a6439ecULL) + F_64(w12,0x90befffa23631e28ULL) + F_64(w13,0xa4506cebde82bde9ULL) + F_64(w14,0xbef9a3f7b2c67915ULL) + F_64(w15,0xc67178f2e372532bULL) + + EXPAND_64 + + F_64(w0 ,0xca273eceea26619cULL) + F_64(w1 ,0xd186b8c721c0c207ULL) + F_64(w2 ,0xeada7dd6cde0eb1eULL) + F_64(w3 ,0xf57d4f7fee6ed178ULL) + F_64(w4 ,0x06f067aa72176fbaULL) + F_64(w5 ,0x0a637dc5a2c898a6ULL) + F_64(w6 ,0x113f9804bef90daeULL) + F_64(w7 ,0x1b710b35131c471bULL) + F_64(w8 ,0x28db77f523047d84ULL) + F_64(w9 ,0x32caab7b40c72493ULL) + F_64(w10,0x3c9ebe0a15c9bebcULL) + F_64(w11,0x431d67c49c100d4cULL) + F_64(w12,0x4cc5d4becb3e42b6ULL) + F_64(w13,0x597f299cfc657e2aULL) + F_64(w14,0x5fcb6fab3ad6faecULL) + F_64(w15,0x6c44198c4a475817ULL) + + a += state[0]; + b += state[1]; + c += state[2]; + d += state[3]; + e += state[4]; + f += state[5]; + g += state[6]; + h += state[7]; + + state[0] = a; + state[1] = b; + state[2] = c; + state[3] = d; + state[4] = e; + state[5] = f; + state[6] = g; + state[7] = h; + + in += 128; + inlen -= 128; + } + + store_bigendian_64(statebytes + 0,state[0]); + store_bigendian_64(statebytes + 8,state[1]); + store_bigendian_64(statebytes + 16,state[2]); + store_bigendian_64(statebytes + 24,state[3]); + store_bigendian_64(statebytes + 32,state[4]); + store_bigendian_64(statebytes + 40,state[5]); + store_bigendian_64(statebytes + 48,state[6]); + store_bigendian_64(statebytes + 56,state[7]); + + return inlen; +} + + +static const uint8_t iv_256[32] = { + 0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, 0x85, + 0x3c, 0x6e, 0xf3, 0x72, 0xa5, 0x4f, 0xf5, 0x3a, + 0x51, 0x0e, 0x52, 0x7f, 0x9b, 0x05, 0x68, 0x8c, + 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19 +}; + +static const uint8_t iv_512[64] = { + 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xbb, 0x67, 0xae, + 0x85, 0x84, 0xca, 0xa7, 0x3b, 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, + 0xf8, 0x2b, 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1, 0x51, + 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1, 0x9b, 0x05, 0x68, 0x8c, + 0x2b, 0x3e, 0x6c, 0x1f, 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, + 0x6b, 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79 +}; + +void sha256_inc_init(uint8_t *state) { + for (size_t i = 0; i < 32; ++i) { + state[i] = iv_256[i]; + } + for (size_t i = 32; i < 40; ++i) { + state[i] = 0; + } +} + +void sha512_inc_init(uint8_t *state) { + for (size_t i = 0; i < 64; ++i) { + state[i] = iv_512[i]; + } + for (size_t i = 64; i < 72; ++i) { + state[i] = 0; + } +} + +void sha256_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks) { + uint64_t bytes = load_bigendian_64(state + 32); + + crypto_hashblocks_sha256(state, in, 64 * inblocks); + bytes += 64 * inblocks; + + store_bigendian_64(state + 32, bytes); +} + +void sha512_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks) { + uint64_t bytes = load_bigendian_64(state + 64); + + crypto_hashblocks_sha512(state, in, 128 * inblocks); + bytes += 128 * inblocks; + + store_bigendian_64(state + 64, bytes); +} + +void sha256_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen) { + uint8_t padded[128]; + uint64_t bytes = load_bigendian_64(state + 32) + inlen; + + crypto_hashblocks_sha256(state, in, inlen); + in += inlen; + inlen &= 63; + in -= inlen; + + for (size_t i = 0; i < inlen; ++i) { + padded[i] = in[i]; + } + padded[inlen] = 0x80; + + if (inlen < 56) { + for (size_t i = inlen + 1; i < 56; ++i) { + padded[i] = 0; + } + padded[56] = (uint8_t) (bytes >> 53); + padded[57] = (uint8_t) (bytes >> 45); + padded[58] = (uint8_t) (bytes >> 37); + padded[59] = (uint8_t) (bytes >> 29); + padded[60] = (uint8_t) (bytes >> 21); + padded[61] = (uint8_t) (bytes >> 13); + padded[62] = (uint8_t) (bytes >> 5); + padded[63] = (uint8_t) (bytes << 3); + crypto_hashblocks_sha256(state, padded, 64); + } else { + for (size_t i = inlen + 1; i < 120; ++i) { + padded[i] = 0; + } + padded[120] = (uint8_t) (bytes >> 53); + padded[121] = (uint8_t) (bytes >> 45); + padded[122] = (uint8_t) (bytes >> 37); + padded[123] = (uint8_t) (bytes >> 29); + padded[124] = (uint8_t) (bytes >> 21); + padded[125] = (uint8_t) (bytes >> 13); + padded[126] = (uint8_t) (bytes >> 5); + padded[127] = (uint8_t) (bytes << 3); + crypto_hashblocks_sha256(state, padded, 128); + } + + for (size_t i = 0; i < 32; ++i) { + out[i] = state[i]; + } + +} + +void sha512_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen) { + uint8_t padded[256]; + uint64_t bytes = load_bigendian_64(state + 64) + inlen; + + crypto_hashblocks_sha512(state, in, inlen); + in += inlen; + inlen &= 127; + in -= inlen; + + for (size_t i = 0; i < inlen; ++i) { + padded[i] = in[i]; + } + padded[inlen] = 0x80; + + if (inlen < 112) { + for (size_t i = inlen + 1; i < 119; ++i) { + padded[i] = 0; + } + padded[119] = (uint8_t) (bytes >> 61); + padded[120] = (uint8_t) (bytes >> 53); + padded[121] = (uint8_t) (bytes >> 45); + padded[122] = (uint8_t) (bytes >> 37); + padded[123] = (uint8_t) (bytes >> 29); + padded[124] = (uint8_t) (bytes >> 21); + padded[125] = (uint8_t) (bytes >> 13); + padded[126] = (uint8_t) (bytes >> 5); + padded[127] = (uint8_t) (bytes << 3); + crypto_hashblocks_sha512(state, padded, 128); + } else { + for (size_t i = inlen + 1; i < 247; ++i) { + padded[i] = 0; + } + padded[247] = (uint8_t) (bytes >> 61); + padded[248] = (uint8_t) (bytes >> 53); + padded[249] = (uint8_t) (bytes >> 45); + padded[250] = (uint8_t) (bytes >> 37); + padded[251] = (uint8_t) (bytes >> 29); + padded[252] = (uint8_t) (bytes >> 21); + padded[253] = (uint8_t) (bytes >> 13); + padded[254] = (uint8_t) (bytes >> 5); + padded[255] = (uint8_t) (bytes << 3); + crypto_hashblocks_sha512(state, padded, 256); + } + + for (size_t i = 0; i < 64; ++i) { + out[i] = state[i]; + } +} + +void sha256(uint8_t *out, const uint8_t *in, size_t inlen) { + uint8_t state[40]; + + sha256_inc_init(state); + sha256_inc_finalize(out, state, in, inlen); +} + +void sha512(uint8_t *out, const uint8_t *in, size_t inlen) { + uint8_t state[72]; + + sha512_inc_init(state); + sha512_inc_finalize(out, state, in, inlen); +} + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) +{ + SPX_VLA(uint8_t, inbuf, inlen+4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + unsigned long i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i+1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i*SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i*SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) +{ + SPX_VLA(uint8_t, inbuf, inlen+4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + unsigned long i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i+1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i*SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i*SPX_SHA512_OUTPUT_BYTES); + } +} + + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(ctx->state_seeded); + sha256_inc_blocks(ctx->state_seeded, block, 1); +#if SPX_SHA512 + sha512_inc_init(ctx->state_seeded_512); + sha512_inc_blocks(ctx->state_seeded_512, block, 1); +#endif +} diff --git a/ref/sha2.h b/ref/sha2.h new file mode 100644 index 0000000..732ab4b --- /dev/null +++ b/ref/sha2.h @@ -0,0 +1,43 @@ +#ifndef SPX_SHA2_H +#define SPX_SHA2_H + +#include "params.h" + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal SPX_N */ + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +#if SPX_SHA256_OUTPUT_BYTES < SPX_N + #error Linking against SHA-256 with N larger than 32 bytes is not supported +#endif + +#define SPX_SHA256_ADDR_BYTES 22 + +#include +#include + +void sha256_inc_init(uint8_t *state); +void sha256_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks); +void sha256_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen); +void sha256(uint8_t *out, const uint8_t *in, size_t inlen); + +void sha512_inc_init(uint8_t *state); +void sha512_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks); +void sha512_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen); +void sha512(uint8_t *out, const uint8_t *in, size_t inlen); + +#define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#define seed_state SPX_NAMESPACE(seed_state) +void seed_state(spx_ctx *ctx); + + +#endif diff --git a/ref/sha2_offsets.h b/ref/sha2_offsets.h new file mode 100644 index 0000000..49f7e85 --- /dev/null +++ b/ref/sha2_offsets.h @@ -0,0 +1,20 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR 10 /* The start of the 4 byte field used to specify the key pair address */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/ref/shake_offsets.h b/ref/shake_offsets.h new file mode 100644 index 0000000..0407bdf --- /dev/null +++ b/ref/shake_offsets.h @@ -0,0 +1,20 @@ +#if !defined( SHAKE_OFFSETS_H_ ) +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR 20 /* The start of the 4 byte field used to specify the key pair address */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/ref/sign.c b/ref/sign.c new file mode 100644 index 0000000..a8e0c3c --- /dev/null +++ b/ref/sign.c @@ -0,0 +1,287 @@ +#include +#include +#include + +#include "api.h" +#include "params.h" +#include "wots.h" +#include "fors.h" +#include "hash.h" +#include "thash.h" +#include "address.h" +#include "randombytes.h" +#include "utils.h" +#include "merkle.h" + +/* + * Returns the length of a secret key, in bytes + */ +unsigned long long crypto_sign_secretkeybytes(void) +{ + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +unsigned long long crypto_sign_publickeybytes(void) +{ + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +unsigned long long crypto_sign_bytes(void) +{ + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +unsigned long long crypto_sign_seedbytes(void) +{ + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, + const unsigned char *seed) +{ + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2*SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3*SPX_N, &ctx); + + memcpy(pk + SPX_N, sk + 3*SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) +{ + unsigned char seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) +{ + spx_ctx ctx; + + const unsigned char *sk_prf = sk + SPX_N; + const unsigned char *pk = sk + 2*SPX_N; + + unsigned char optrand[SPX_N]; + unsigned char mhash[SPX_FORS_MSG_BYTES]; + unsigned char root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT)-1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) +{ + spx_ctx ctx; + const unsigned char *pub_root = pk + SPX_N; + unsigned char mhash[SPX_FORS_MSG_BYTES]; + unsigned char wots_pk[SPX_WOTS_BYTES]; + unsigned char root[SPX_N]; + unsigned char leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT)-1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N)) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sk) +{ + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, (size_t)mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(unsigned char *m, unsigned long long *mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk) +{ + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, (size_t)*mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/ref/test/benchmark.c b/ref/test/benchmark.c new file mode 100644 index 0000000..b062545 --- /dev/null +++ b/ref/test/benchmark.c @@ -0,0 +1,173 @@ +#define _POSIX_C_SOURCE 199309L + +#include +#include +#include + +#include "../thash.h" +#include "../api.h" +#include "../fors.h" +#include "../wotsx1.h" +#include "../params.h" +#include "../randombytes.h" +#include "cycles.h" + +#define SPX_MLEN 32 +#define NTESTS 10 + +static void wots_gen_pkx1(unsigned char *pk, const spx_ctx* ctx, + uint32_t addr[8]); + +static int cmp_llu(const void *a, const void*b) +{ + if(*(unsigned long long *)a < *(unsigned long long *)b) return -1; + if(*(unsigned long long *)a > *(unsigned long long *)b) return 1; + return 0; +} + +static unsigned long long median(unsigned long long *l, size_t llen) +{ + qsort(l,llen,sizeof(unsigned long long),cmp_llu); + + if(llen%2) return l[llen/2]; + else return (l[llen/2-1]+l[llen/2])/2; +} + +static void delta(unsigned long long *l, size_t llen) +{ + unsigned int i; + for(i = 0; i < llen - 1; i++) { + l[i] = l[i+1] - l[i]; + } +} + + +static void printfcomma (unsigned long long n) +{ + if (n < 1000) { + printf("%llu", n); + return; + } + printfcomma(n / 1000); + printf (",%03llu", n % 1000); +} + +static void printfalignedcomma (unsigned long long n, int len) +{ + unsigned long long ncopy = n; + int i = 0; + + while (ncopy > 9) { + len -= 1; + ncopy /= 10; + i += 1; // to account for commas + } + i = i/3 - 1; // to account for commas + for (; i < len; i++) { + printf(" "); + } + printfcomma(n); +} + +static void display_result(double result, unsigned long long *l, size_t llen, unsigned long long mul) +{ + unsigned long long med; + + result /= NTESTS; + delta(l, NTESTS + 1); + med = median(l, llen); + printf("avg. %11.2lf us (%2.2lf sec); median ", result, result / 1e6); + printfalignedcomma(med, 12); + printf(" cycles, %5llux: ", mul); + printfalignedcomma(mul*med, 12); + printf(" cycles\n"); +} + +#define MEASURE_GENERIC(TEXT, MUL, FNCALL, CORR)\ + printf(TEXT);\ + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);\ + for(i = 0; i < NTESTS; i++) {\ + t[i] = cpucycles() / CORR;\ + FNCALL;\ + }\ + t[NTESTS] = cpucycles();\ + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop);\ + result = ((stop.tv_sec - start.tv_sec) * 1e6 + \ + (stop.tv_nsec - start.tv_nsec) / 1e3) / (double)CORR;\ + display_result(result, t, NTESTS, MUL); +#define MEASURT(TEXT, MUL, FNCALL)\ + MEASURE_GENERIC(\ + TEXT, MUL,\ + do {\ + for (int j = 0; j < 1000; j++) {\ + FNCALL;\ + }\ + } while (0);,\ + 1000); +#define MEASURE(TEXT, MUL, FNCALL) MEASURE_GENERIC(TEXT, MUL, FNCALL, 1) + +int main(void) +{ + /* Make stdout buffer more responsive. */ + setbuf(stdout, NULL); + init_cpucycles(); + + spx_ctx ctx; + + unsigned char pk[SPX_PK_BYTES]; + unsigned char sk[SPX_SK_BYTES]; + unsigned char *m = malloc(SPX_MLEN); + unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); + unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); + + unsigned char fors_pk[SPX_FORS_PK_BYTES]; + unsigned char fors_m[SPX_FORS_MSG_BYTES]; + unsigned char fors_sig[SPX_FORS_BYTES]; + unsigned char addr[SPX_ADDR_BYTES]; + unsigned char block[SPX_N]; + + unsigned char wots_pk[SPX_WOTS_PK_BYTES]; + + unsigned long long smlen; + unsigned long long mlen; + unsigned long long t[NTESTS+1]; + struct timespec start, stop; + double result; + int i; + + randombytes(m, SPX_MLEN); + randombytes(addr, SPX_ADDR_BYTES); + + printf("Parameters: n = %d, h = %d, d = %d, b = %d, k = %d, w = %d\n", + SPX_N, SPX_FULL_HEIGHT, SPX_D, SPX_FORS_HEIGHT, SPX_FORS_TREES, + SPX_WOTS_W); + + printf("Running %d iterations.\n", NTESTS); + + MEASURT("thash ", 1, thash(block, block, 1, &ctx, (uint32_t*)addr)); + MEASURE("Generating keypair.. ", 1, crypto_sign_keypair(pk, sk)); + MEASURE(" - WOTS pk gen.. ", (1 << SPX_TREE_HEIGHT), wots_gen_pkx1(wots_pk, &ctx, (uint32_t *) addr)); + MEASURE("Signing.. ", 1, crypto_sign(sm, &smlen, m, SPX_MLEN, sk)); + MEASURE(" - FORS signing.. ", 1, fors_sign(fors_sig, fors_pk, fors_m, &ctx, (uint32_t *) addr)); + MEASURE(" - WOTS pk gen.. ", SPX_D * (1 << SPX_TREE_HEIGHT), wots_gen_pkx1(wots_pk, &ctx, (uint32_t *) addr)); + MEASURE("Verifying.. ", 1, crypto_sign_open(mout, &mlen, sm, smlen, pk)); + + printf("Signature size: %d (%.2f KiB)\n", SPX_BYTES, SPX_BYTES / 1024.0); + printf("Public key size: %d (%.2f KiB)\n", SPX_PK_BYTES, SPX_PK_BYTES / 1024.0); + printf("Secret key size: %d (%.2f KiB)\n", SPX_SK_BYTES, SPX_SK_BYTES / 1024.0); + + free(m); + free(sm); + free(mout); + + return 0; +} + +static void wots_gen_pkx1(unsigned char *pk, const spx_ctx *ctx, + uint32_t addr[8]) { + struct leaf_info_x1 leaf; + unsigned steps[ SPX_WOTS_LEN ] = { 0 }; + INITIALIZE_LEAF_INFO_X1(leaf, addr, steps); + wots_gen_leafx1(pk, ctx, 0, &leaf); +} + diff --git a/ref/test/cycles.c b/ref/test/cycles.c new file mode 100644 index 0000000..0fa46b5 --- /dev/null +++ b/ref/test/cycles.c @@ -0,0 +1,110 @@ +#include "cycles.h" + +#if defined(__aarch64__) && defined(__APPLE__) +// Adapted from +// https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2021/03/24/ + +#include +#include +#include +#include + +#define KPERF_LIST \ + F(int, kpc_force_all_ctrs_set, int) \ + F(int, kpc_set_counting, uint32_t) \ + F(int, kpc_set_thread_counting, uint32_t) \ + F(int, kpc_set_config, uint32_t, void *) \ + F(uint32_t, kpc_get_counter_count, uint32_t) \ + F(uint32_t, kpc_get_config_count, uint32_t) \ + F(int, kpc_get_thread_counters, int, unsigned int, void *) + +#define F(ret, name, ...) \ + typedef ret name##proc(__VA_ARGS__); \ + static name##proc *name; +KPERF_LIST +#undef F + +uint64_t g_counters[10]; +uint64_t g_config[10]; + +static void configure_rdtsc(void) { + if (kpc_set_config(3, g_config)) { + printf("kpc_set_config failed\n"); + return; + } + + if (kpc_force_all_ctrs_set(1)) { + printf("kpc_force_all_ctrs_set failed\n"); + return; + } + + if (kpc_set_counting(3)) { + printf("kpc_set_counting failed\n"); + return; + } + + if (kpc_set_thread_counting(3)) { + printf("kpc_set_thread_counting failed\n"); + return; + } +} + +void init_cpucycles(void) { + void *kperf = dlopen( + "/System/Library/PrivateFrameworks/kperf.framework/Versions/A/kperf", + RTLD_LAZY); + if (!kperf) { + printf("kperf = %p\n", kperf); + return; + } +#define F(ret, name, ...) \ + name = (name##proc *)(dlsym(kperf, #name)); \ + if (!name) { \ + printf("%s = %p\n", #name, (void *)name); \ + return; \ + } + KPERF_LIST +#undef F + + if (kpc_get_counter_count(3) != 10) { + printf("wrong fixed counters count\n"); + return; + } + + if (kpc_get_config_count(3) != 8) { + printf("wrong fixed config count\n"); + return; + } + g_config[0] = 0x02 | 0x20000; + g_config[3] = 0x8d | 0x20000; + g_config[4] = 0xcb | 0x20000; + g_config[5] = 0x8c | 0x20000; + + configure_rdtsc(); +} + +unsigned long long cpucycles(void) { + static int warned = 0; + if (kpc_get_thread_counters(0, 10, g_counters)) { + if (!warned) { + printf("kpc_get_thread_counters failed, run as sudo?\n"); + warned = 1; + } + return 1; + } + // g_counters[3 + 2] gives you the number of instructions 'decoded' + // whereas g_counters[1] might give you the number of instructions 'retired'. + return g_counters[0 + 2]; +} +#else +void init_cpucycles(void) { +} + +unsigned long long cpucycles(void) +{ + unsigned long long result; + __asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax" + : "=a" (result) :: "%rdx"); + return result; +} +#endif diff --git a/ref/test/cycles.h b/ref/test/cycles.h new file mode 100644 index 0000000..913a9a5 --- /dev/null +++ b/ref/test/cycles.h @@ -0,0 +1,7 @@ +#ifndef SPX_CYCLES_H +#define SPX_CYCLES_H + +void init_cpucycles(void); +unsigned long long cpucycles(void); + +#endif diff --git a/ref/test/fors.c b/ref/test/fors.c new file mode 100644 index 0000000..73c828d --- /dev/null +++ b/ref/test/fors.c @@ -0,0 +1,41 @@ +#include +#include + +#include "../context.h" +#include "../hash.h" +#include "../fors.h" +#include "../randombytes.h" +#include "../params.h" + +int main(void) +{ + /* Make stdout buffer more responsive. */ + setbuf(stdout, NULL); + + spx_ctx ctx; + + unsigned char pk1[SPX_FORS_PK_BYTES]; + unsigned char pk2[SPX_FORS_PK_BYTES]; + unsigned char sig[SPX_FORS_BYTES]; + unsigned char m[SPX_FORS_MSG_BYTES]; + uint32_t addr[8] = {0}; + + randombytes(ctx.sk_seed, SPX_N); + randombytes(ctx.pub_seed, SPX_N); + randombytes(m, SPX_FORS_MSG_BYTES); + randombytes((unsigned char *)addr, 8 * sizeof(uint32_t)); + + printf("Testing FORS signature and PK derivation.. "); + + initialize_hash_function(&ctx); + + fors_sign(sig, pk1, m, &ctx, addr); + fors_pk_from_sig(pk2, sig, m, &ctx, addr); + + if (memcmp(pk1, pk2, SPX_FORS_PK_BYTES)) { + printf("failed!\n"); + return -1; + } + printf("successful.\n"); + return 0; +} diff --git a/ref/test/haraka.c b/ref/test/haraka.c new file mode 100644 index 0000000..927d0de --- /dev/null +++ b/ref/test/haraka.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include + +#include "../haraka.c" +#include "../randombytes.h" + +static int test_haraka_S_incremental(void) { + unsigned char input[521]; + unsigned char check[521]; + unsigned char output[521]; + uint8_t s_inc_absorb[65]; + uint8_t s_inc_squeeze[65]; + uint8_t s_inc_squeeze_all[65]; + uint8_t s_inc_both[65]; + uint8_t s_combined[64]; + int i; + int absorbed; + int squeezed; + int returncode = 0; + + randombytes(input, 521); + + haraka_S(check, 521, input, 521); + + haraka_S_inc_init(s_inc_absorb); + + absorbed = 0; + for (i = 0; i < 521 && absorbed + i <= 521; i++) { + haraka_S_inc_absorb(s_inc_absorb, input + absorbed, i); + absorbed += i; + } + haraka_S_inc_absorb(s_inc_absorb, input + absorbed, 521 - absorbed); + + haraka_S_inc_finalize(s_inc_absorb); + + memset(s_combined, 0, 64); + haraka_S_absorb(s_combined, HARAKAS_RATE, input, 521, 0x1F); + + if (memcmp(s_inc_absorb, s_combined, 64 * sizeof(uint8_t))) { + printf("ERROR haraka_S state after incremental absorb did not match all-at-once absorb.\n"); + printf(" Expected: "); + for (i = 0; i < 64; i++) { + printf("%02X", s_combined[i]); + } + printf("\n"); + printf(" State: "); + for (i = 0; i < 64; i++) { + printf("%02X", s_inc_absorb[i]); + } + printf("\n"); + returncode = 1; + } + + memcpy(s_inc_both, s_inc_absorb, 65 * sizeof(uint8_t)); + + haraka_S_squeezeblocks(output, 3, s_inc_absorb, HARAKAS_RATE); + + if (memcmp(check, output, 3*HARAKAS_RATE)) { + printf("ERROR haraka_S incremental absorb did not match haraka_S.\n"); + printf(" Expected: "); + for (i = 0; i < 3*HARAKAS_RATE; i++) { + printf("%02X", check[i]); + } + printf("\n"); + printf(" Received: "); + for (i = 0; i < 3*HARAKAS_RATE; i++) { + printf("%02X", output[i]); + } + printf("\n"); + returncode = 1; + } + + memset(s_inc_squeeze, 0, 65); + haraka_S_absorb(s_inc_squeeze, HARAKAS_RATE, input, 521, 0x1F); + s_inc_squeeze[64] = 0; + + memcpy(s_inc_squeeze_all, s_inc_squeeze, 65 * sizeof(uint8_t)); + + haraka_S_inc_squeeze(output, 521, s_inc_squeeze_all); + + if (memcmp(check, output, 521)) { + printf("ERROR haraka_S incremental squeeze-all did not match haraka_S.\n"); + printf(" Expected: "); + for (i = 0; i < 521; i++) { + printf("%02X", check[i]); + } + printf("\n"); + printf(" Received: "); + for (i = 0; i < 521; i++) { + printf("%02X", output[i]); + } + printf("\n"); + returncode = 1; + } + + squeezed = 0; + memset(output, 0, 521); + for (i = 0; i < 521 && squeezed + i <= 521; i++) { + haraka_S_inc_squeeze(output + squeezed, i, s_inc_squeeze); + squeezed += i; + } + haraka_S_inc_squeeze(output + squeezed, 521 - squeezed, s_inc_squeeze); + + if (memcmp(check, output, 521)) { + printf("ERROR haraka_S incremental squeeze did not match haraka_S.\n"); + printf(" Expected: "); + for (i = 0; i < 521; i++) { + printf("%02X", check[i]); + } + printf("\n"); + printf(" Received: "); + for (i = 0; i < 521; i++) { + printf("%02X", output[i]); + } + printf("\n"); + returncode = 1; + } + + squeezed = 0; + memset(output, 0, 521); + for (i = 0; i < 521 && squeezed + i <= 521; i++) { + haraka_S_inc_squeeze(output + squeezed, i, s_inc_both); + squeezed += i; + } + haraka_S_inc_squeeze(output + squeezed, 521 - squeezed, s_inc_both); + + if (memcmp(check, output, 521)) { + printf("ERROR haraka_S incremental absorb + squeeze did not match haraka_S.\n"); + printf(" Expected: "); + for (i = 0; i < 521; i++) { + printf("%02X", check[i]); + } + printf("\n"); + printf(" Received: "); + for (i = 0; i < 521; i++) { + printf("%02X", output[i]); + } + printf("\n"); + returncode = 1; + } + + return returncode; +} + +int main(void) { + int result = 0; + result += test_haraka_S_incremental(); + + if (result != 0) { + puts("Errors occurred"); + } + return result; +} diff --git a/ref/test/spx.c b/ref/test/spx.c new file mode 100644 index 0000000..2b214b9 --- /dev/null +++ b/ref/test/spx.c @@ -0,0 +1,125 @@ +#include +#include +#include + +#include "../api.h" +#include "../params.h" +#include "../randombytes.h" + +#define SPX_MLEN 32 +#define SPX_SIGNATURES 1 + +int main(void) +{ + int ret = 0; + int i; + + /* Make stdout buffer more responsive. */ + setbuf(stdout, NULL); + + unsigned char pk[SPX_PK_BYTES]; + unsigned char sk[SPX_SK_BYTES]; + unsigned char *m = malloc(SPX_MLEN); + unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); + unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); + unsigned long long smlen; + unsigned long long mlen; + + randombytes(m, SPX_MLEN); + + printf("Generating keypair.. "); + + if (crypto_sign_keypair(pk, sk)) { + printf("failed!\n"); + return -1; + } + printf("successful.\n"); + + printf("Testing %d signatures.. \n", SPX_SIGNATURES); + + for (i = 0; i < SPX_SIGNATURES; i++) { + printf(" - iteration #%d:\n", i); + + crypto_sign(sm, &smlen, m, SPX_MLEN, sk); + + if (smlen != SPX_BYTES + SPX_MLEN) { + printf(" X smlen incorrect [%llu != %u]!\n", + smlen, SPX_BYTES); + ret = -1; + } + else { + printf(" smlen as expected [%llu].\n", smlen); + } + + /* Test if signature is valid. */ + if (crypto_sign_open(mout, &mlen, sm, smlen, pk)) { + printf(" X verification failed!\n"); + ret = -1; + } + else { + printf(" verification succeeded.\n"); + } + + /* Test if the correct message was recovered. */ + if (mlen != SPX_MLEN) { + printf(" X mlen incorrect [%llu != %u]!\n", mlen, SPX_MLEN); + ret = -1; + } + else { + printf(" mlen as expected [%llu].\n", mlen); + } + if (memcmp(m, mout, SPX_MLEN)) { + printf(" X output message incorrect!\n"); + ret = -1; + } + else { + printf(" output message as expected.\n"); + } + + /* Test if signature is valid when validating in-place. */ + if (crypto_sign_open(sm, &mlen, sm, smlen, pk)) { + printf(" X in-place verification failed!\n"); + ret = -1; + } + else { + printf(" in-place verification succeeded.\n"); + } + + /* Test if flipping bits invalidates the signature (it should). */ + + /* Flip the first bit of the message. Should invalidate. */ + sm[smlen - 1] ^= 1; + if (!crypto_sign_open(mout, &mlen, sm, smlen, pk)) { + printf(" X flipping a bit of m DID NOT invalidate signature!\n"); + ret = -1; + } + else { + printf(" flipping a bit of m invalidates signature.\n"); + } + sm[smlen - 1] ^= 1; + +#ifdef SPX_TEST_INVALIDSIG + int j; + /* Flip one bit per hash; the signature is entirely hashes. */ + for (j = 0; j < (int)(smlen - SPX_MLEN); j += SPX_N) { + sm[j] ^= 1; + if (!crypto_sign_open(mout, &mlen, sm, smlen, pk)) { + printf(" X flipping bit %d DID NOT invalidate sig + m!\n", j); + sm[j] ^= 1; + ret = -1; + break; + } + sm[j] ^= 1; + } + if (j >= (int)(smlen - SPX_MLEN)) { + printf(" changing any signature hash invalidates signature.\n"); + } +#endif + } + + free(m); + free(sm); + free(mout); + + return ret; +} diff --git a/ref/thash.h b/ref/thash.h new file mode 100644 index 0000000..8687ccf --- /dev/null +++ b/ref/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/ref/thash_haraka_robust.c b/ref/thash_haraka_robust.c new file mode 100644 index 0000000..005e14a --- /dev/null +++ b/ref/thash_haraka_robust.c @@ -0,0 +1,46 @@ +#include +#include + +#include "thash.h" +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "haraka.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) +{ + SPX_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(uint8_t, bitmask, inblocks*SPX_N); + unsigned char outbuf[32]; + unsigned char buf_tmp[64]; + unsigned int i; + + if (inblocks == 1) { + /* F function */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ + memset(buf_tmp, 0, 64); + memcpy(buf_tmp, addr, 32); + + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + } + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks*SPX_N, ctx); + } +} diff --git a/ref/thash_haraka_simple.c b/ref/thash_haraka_simple.c new file mode 100644 index 0000000..1040297 --- /dev/null +++ b/ref/thash_haraka_simple.c @@ -0,0 +1,37 @@ +#include +#include + +#include "thash.h" +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "haraka.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) +{ + SPX_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks*SPX_N); + unsigned char outbuf[32]; + unsigned char buf_tmp[64]; + + if (inblocks == 1) { + /* F function */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ + memset(buf_tmp, 0, 64); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); + + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks*SPX_N, ctx); + } +} diff --git a/ref/thash_sha2_robust.c b/ref/thash_sha2_robust.c new file mode 100644 index 0000000..67ca3da --- /dev/null +++ b/ref/thash_sha2_robust.c @@ -0,0 +1,74 @@ +#include +#include + +#include "thash.h" +#include "address.h" +#include "params.h" +#include "utils.h" +#include "sha2.h" + +#if SPX_SHA512 +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); +#endif + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) +{ +#if SPX_SHA512 + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } +#endif + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + SPX_VLA(uint8_t, bitmask, inblocks * SPX_N); + SPX_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks*SPX_N); + uint8_t sha2_state[40]; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + memcpy(sha2_state, ctx->state_seeded, 40 * sizeof(uint8_t)); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); + memcpy(out, outbuf, SPX_N); +} + +#if SPX_SHA512 +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) +{ + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + SPX_VLA(uint8_t, bitmask, inblocks * SPX_N); + SPX_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); + uint8_t sha2_state[72]; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + memcpy(sha2_state, ctx->state_seeded_512, 72 * sizeof(uint8_t)); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha512_inc_finalize(outbuf, sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); + memcpy(out, outbuf, SPX_N); +} +#endif diff --git a/ref/thash_sha2_simple.c b/ref/thash_sha2_simple.c new file mode 100644 index 0000000..da58896 --- /dev/null +++ b/ref/thash_sha2_simple.c @@ -0,0 +1,59 @@ +#include +#include + +#include "thash.h" +#include "address.h" +#include "params.h" +#include "utils.h" +#include "sha2.h" + +#if SPX_SHA512 +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); +#endif + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) +{ +#if SPX_SHA512 + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } +#endif + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint8_t sha2_state[40]; + SPX_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + memcpy(sha2_state, ctx->state_seeded, 40 * sizeof(uint8_t)); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); + memcpy(out, outbuf, SPX_N); +} + +#if SPX_SHA512 +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) +{ + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint8_t sha2_state[72]; + SPX_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + memcpy(sha2_state, ctx->state_seeded_512, 72 * sizeof(uint8_t)); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha512_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks*SPX_N); + memcpy(out, outbuf, SPX_N); +} +#endif diff --git a/ref/thash_shake_robust.c b/ref/thash_shake_robust.c new file mode 100644 index 0000000..3589fde --- /dev/null +++ b/ref/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) +{ + SPX_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); +} diff --git a/ref/thash_shake_simple.c b/ref/thash_shake_simple.c new file mode 100644 index 0000000..7ce5c55 --- /dev/null +++ b/ref/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) +{ + SPX_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); +} diff --git a/ref/utils.c b/ref/utils.c new file mode 100644 index 0000000..63d52ee --- /dev/null +++ b/ref/utils.c @@ -0,0 +1,154 @@ +#include + +#include "utils.h" +#include "params.h" +#include "hash.h" +#include "thash.h" +#include "address.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) +{ + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) +{ + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) +{ + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8*(inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) +{ + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } + else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } + else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx* ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char* /* leaf */, + const spx_ctx* /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) +{ + SPX_VLA(uint8_t, stack, (tree_height+1)*SPX_N); + SPX_VLA(unsigned int, heights, tree_height+1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset*SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset-1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/ref/utils.h b/ref/utils.h new file mode 100644 index 0000000..b13502c --- /dev/null +++ b/ref/utils.h @@ -0,0 +1,64 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include +#include "params.h" +#include "context.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ +#ifdef _MSC_VER +/* MSVC defines _alloca in malloc.h */ +# include +/* Note: _malloca(), which is recommended over deprecated _alloca, + requires that you call _freea(). So we stick with _alloca */ +# define SPX_VLA(__t,__x,__s) __t *__x = (__t*)_alloca((__s)*sizeof(__t)) +#else +# define SPX_VLA(__t,__x,__s) __t __x[__s] +#endif + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx* ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char* /* leaf */, + const spx_ctx* ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/ref/utilsx1.c b/ref/utilsx1.c new file mode 100644 index 0000000..f6a6700 --- /dev/null +++ b/ref/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utils.h" +#include "utilsx1.h" +#include "params.h" +#include "thash.h" +#include "address.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx* ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char* /* Where to write the leaves */, + const spx_ctx* /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) +{ + /* This is where we keep the intermediate nodes */ + SPX_VLA(uint8_t, stack, tree_height*SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2*SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h=0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx/2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/ref/utilsx1.h b/ref/utilsx1.h new file mode 100644 index 0000000..a7fcf15 --- /dev/null +++ b/ref/utilsx1.h @@ -0,0 +1,26 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include +#include "params.h" +#include "context.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx* ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char* /* Where to write the leaf */, + const spx_ctx* /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/ref/wots.c b/ref/wots.c new file mode 100644 index 0000000..df83278 --- /dev/null +++ b/ref/wots.c @@ -0,0 +1,112 @@ +#include +#include + +#include "utils.h" +#include "utilsx1.h" +#include "hash.h" +#include "thash.h" +#include "wots.h" +#include "wotsx1.h" +#include "address.h" +#include "params.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) +{ + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start+steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) +{ + int in = 0; + int out = 0; + unsigned char total; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) +{ + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) +{ + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) +{ + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i*SPX_N, sig + i*SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/ref/wots.h b/ref/wots.h new file mode 100644 index 0000000..7e77056 --- /dev/null +++ b/ref/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "params.h" +#include "context.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/ref/wotsx1.c b/ref/wotsx1.c new file mode 100644 index 0000000..dfb3780 --- /dev/null +++ b/ref/wotsx1.c @@ -0,0 +1,73 @@ +#include +#include + +#include "utils.h" +#include "hash.h" +#include "thash.h" +#include "wots.h" +#include "wotsx1.h" +#include "address.h" +#include "params.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k=0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) break; + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/ref/wotsx1.h b/ref/wotsx1.h new file mode 100644 index 0000000..1257f81 --- /dev/null +++ b/ref/wotsx1.h @@ -0,0 +1,36 @@ +#if !defined( WOTSX1_H_ ) +#define WOTSX1_H_ + +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + info.wots_sig = 0; \ + info.wots_sign_leaf = ~0u; \ + info.wots_steps = step_buffer; \ + memcpy( &info.leaf_addr[0], addr, 32 ); \ + memcpy( &info.pk_addr[0], addr, 32 ); \ +} + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/sha2-avx2/.gitignore b/sha2-avx2/.gitignore new file mode 100644 index 0000000..20d83ac --- /dev/null +++ b/sha2-avx2/.gitignore @@ -0,0 +1,6 @@ +test/* +!test/*.c +PQCsignKAT_*.rsp +PQCsignKAT_*.req +PQCgenKAT_sign +keccak4x/KeccakP-1600-times4-SIMD256.o \ No newline at end of file diff --git a/sha2-avx2/Makefile b/sha2-avx2/Makefile new file mode 100644 index 0000000..f708543 --- /dev/null +++ b/sha2-avx2/Makefile @@ -0,0 +1,48 @@ +PARAMS = sphincs-sha2-128f +THASH = robust + +CC = /usr/bin/gcc +CFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3 -std=c99 -march=native -flto -fomit-frame-pointer -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) + + +SOURCES = hash_sha2.c hash_sha2x8.c thash_sha2_$(THASH).c thash_sha2_$(THASH)x8.c sha2.c sha256x8.c sha512x4.c sha256avx.c address.c randombytes.c merkle.c wots.c utils.c utilsx8.c fors.c sign.c +HEADERS = params.h hash.h hashx8.h thash.h thashx8.h sha2.h sha256x8.h sha512x4.h sha256avx.h address.h randombytes.h merkle.h wots.h utils.h utilsx8.h fors.h api.h + +DET_SOURCES = $(SOURCES:randombytes.%=rng.%) +DET_HEADERS = $(HEADERS:randombytes.%=rng.%) + +TESTS = test/fors \ + test/spx \ + test/thashx8 \ + +BENCHMARK = test/benchmark + +.PHONY: clean test benchmark + +default: PQCgenKAT_sign + +all: PQCgenKAT_sign tests benchmarks + +tests: $(TESTS) + +test: $(TESTS:=.exec) + +benchmarks: $(BENCHMARK) + +benchmark: $(BENCHMARK:=.exec) + +PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) + $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto + +test/%: test/%.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) + +test/%.exec: test/% + @$< + +clean: + -$(RM) $(TESTS) + -$(RM) $(BENCHMARK) + -$(RM) PQCgenKAT_sign + -$(RM) PQCsignKAT_*.rsp + -$(RM) PQCsignKAT_*.req diff --git a/sha2-avx2/PQCgenKAT_sign.c b/sha2-avx2/PQCgenKAT_sign.c new file mode 120000 index 0000000..a17dbe2 --- /dev/null +++ b/sha2-avx2/PQCgenKAT_sign.c @@ -0,0 +1 @@ +../ref/PQCgenKAT_sign.c \ No newline at end of file diff --git a/sha2-avx2/address.c b/sha2-avx2/address.c new file mode 120000 index 0000000..02c52c6 --- /dev/null +++ b/sha2-avx2/address.c @@ -0,0 +1 @@ +../ref/address.c \ No newline at end of file diff --git a/sha2-avx2/address.h b/sha2-avx2/address.h new file mode 120000 index 0000000..e670da5 --- /dev/null +++ b/sha2-avx2/address.h @@ -0,0 +1 @@ +../ref/address.h \ No newline at end of file diff --git a/sha2-avx2/api.h b/sha2-avx2/api.h new file mode 120000 index 0000000..ea89e0a --- /dev/null +++ b/sha2-avx2/api.h @@ -0,0 +1 @@ +../ref/api.h \ No newline at end of file diff --git a/sha2-avx2/context.h b/sha2-avx2/context.h new file mode 100644 index 0000000..05ffbe8 --- /dev/null +++ b/sha2-avx2/context.h @@ -0,0 +1,18 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + uint8_t state_seeded[40]; +#if SPX_SHA512 + uint8_t state_seeded_512[72]; +#endif +} spx_ctx; + +#endif diff --git a/sha2-avx2/fors.c b/sha2-avx2/fors.c new file mode 100644 index 0000000..67ad322 --- /dev/null +++ b/sha2-avx2/fors.c @@ -0,0 +1,233 @@ +#include +#include +#include + +#include "fors.h" +#include "utils.h" +#include "utilsx8.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "address.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) +{ + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8*8]) +{ + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) +{ + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8*8]) +{ + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8*8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) +{ + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j*8, addr_idx + j); + set_type(fors_leaf_addrx8 + j*8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0*SPX_N, + leaf + 1*SPX_N, + leaf + 2*SPX_N, + leaf + 3*SPX_N, + leaf + 4*SPX_N, + leaf + 5*SPX_N, + leaf + 6*SPX_N, + leaf + 7*SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j*8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0*SPX_N, + leaf + 1*SPX_N, + leaf + 2*SPX_N, + leaf + 3*SPX_N, + leaf + 4*SPX_N, + leaf + 5*SPX_N, + leaf + 6*SPX_N, + leaf + 7*SPX_N, + leaf + 0*SPX_N, + leaf + 1*SPX_N, + leaf + 2*SPX_N, + leaf + 3*SPX_N, + leaf + 4*SPX_N, + leaf + 5*SPX_N, + leaf + 6*SPX_N, + leaf + 7*SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) +{ + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= ((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) +{ + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8*8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i=0; i<8; i++) { + copy_keypair_addr(fors_tree_addr + 8*i, fors_addr); + set_type(fors_tree_addr + 8*i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8*i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i*SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) +{ + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i*SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/sha2-avx2/fors.h b/sha2-avx2/fors.h new file mode 120000 index 0000000..07156bd --- /dev/null +++ b/sha2-avx2/fors.h @@ -0,0 +1 @@ +../ref/fors.h \ No newline at end of file diff --git a/sha2-avx2/hash.h b/sha2-avx2/hash.h new file mode 120000 index 0000000..cffc52b --- /dev/null +++ b/sha2-avx2/hash.h @@ -0,0 +1 @@ +../ref/hash.h \ No newline at end of file diff --git a/sha2-avx2/hash_sha2.c b/sha2-avx2/hash_sha2.c new file mode 120000 index 0000000..cfd85d4 --- /dev/null +++ b/sha2-avx2/hash_sha2.c @@ -0,0 +1 @@ +../ref/hash_sha2.c \ No newline at end of file diff --git a/sha2-avx2/hash_sha2x8.c b/sha2-avx2/hash_sha2x8.c new file mode 100644 index 0000000..3f59b9a --- /dev/null +++ b/sha2-avx2/hash_sha2x8.c @@ -0,0 +1,74 @@ +#include +#include + +#include "address.h" +#include "utils.h" +#include "params.h" +#include "hashx8.h" +#include "sha2.h" +#include "sha256x8.h" +#include "sha256avx.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8*8]) +{ + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j*(SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j*8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j*(SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + ctx->state_seeded, 512, + + /* in */ + bufx8 + 0*(SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1*(SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2*(SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3*(SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4*(SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5*(SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6*(SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7*(SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/sha2-avx2/hashx8.h b/sha2-avx2/hashx8.h new file mode 100644 index 0000000..dc924b4 --- /dev/null +++ b/sha2-avx2/hashx8.h @@ -0,0 +1,19 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8*8]); + +#endif diff --git a/sha2-avx2/merkle.c b/sha2-avx2/merkle.c new file mode 100644 index 0000000..0b3f666 --- /dev/null +++ b/sha2-avx2/merkle.c @@ -0,0 +1,67 @@ +#include +#include + +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" +#include "wotsx8.h" +#include "merkle.h" +#include "address.h" +#include "params.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) +{ + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8*8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j=0; j<8; j++) { + set_type(&tree_addrx8[8*j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8*j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8*j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8*j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8*j], wots_addr); + copy_subtree_addr(&info.pk_addr[8*j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) +{ + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/sha2-avx2/merkle.h b/sha2-avx2/merkle.h new file mode 120000 index 0000000..7d167ed --- /dev/null +++ b/sha2-avx2/merkle.h @@ -0,0 +1 @@ +../ref/merkle.h \ No newline at end of file diff --git a/sha2-avx2/params.h b/sha2-avx2/params.h new file mode 120000 index 0000000..53133cc --- /dev/null +++ b/sha2-avx2/params.h @@ -0,0 +1 @@ +../ref/params.h \ No newline at end of file diff --git a/sha2-avx2/params/params-sphincs-sha2-128f.h b/sha2-avx2/params/params-sphincs-sha2-128f.h new file mode 120000 index 0000000..d901a75 --- /dev/null +++ b/sha2-avx2/params/params-sphincs-sha2-128f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-sha2-128f.h \ No newline at end of file diff --git a/sha2-avx2/params/params-sphincs-sha2-128s.h b/sha2-avx2/params/params-sphincs-sha2-128s.h new file mode 120000 index 0000000..a9955de --- /dev/null +++ b/sha2-avx2/params/params-sphincs-sha2-128s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-sha2-128s.h \ No newline at end of file diff --git a/sha2-avx2/params/params-sphincs-sha2-192f.h b/sha2-avx2/params/params-sphincs-sha2-192f.h new file mode 120000 index 0000000..ecbc980 --- /dev/null +++ b/sha2-avx2/params/params-sphincs-sha2-192f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-sha2-192f.h \ No newline at end of file diff --git a/sha2-avx2/params/params-sphincs-sha2-192s.h b/sha2-avx2/params/params-sphincs-sha2-192s.h new file mode 120000 index 0000000..c2db1ba --- /dev/null +++ b/sha2-avx2/params/params-sphincs-sha2-192s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-sha2-192s.h \ No newline at end of file diff --git a/sha2-avx2/params/params-sphincs-sha2-256f.h b/sha2-avx2/params/params-sphincs-sha2-256f.h new file mode 120000 index 0000000..b388615 --- /dev/null +++ b/sha2-avx2/params/params-sphincs-sha2-256f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-sha2-256f.h \ No newline at end of file diff --git a/sha2-avx2/params/params-sphincs-sha2-256s.h b/sha2-avx2/params/params-sphincs-sha2-256s.h new file mode 120000 index 0000000..420ffec --- /dev/null +++ b/sha2-avx2/params/params-sphincs-sha2-256s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-sha2-256s.h \ No newline at end of file diff --git a/sha2-avx2/randombytes.c b/sha2-avx2/randombytes.c new file mode 120000 index 0000000..59a42a5 --- /dev/null +++ b/sha2-avx2/randombytes.c @@ -0,0 +1 @@ +../ref/randombytes.c \ No newline at end of file diff --git a/sha2-avx2/randombytes.h b/sha2-avx2/randombytes.h new file mode 120000 index 0000000..055e443 --- /dev/null +++ b/sha2-avx2/randombytes.h @@ -0,0 +1 @@ +../ref/randombytes.h \ No newline at end of file diff --git a/sha2-avx2/rng.c b/sha2-avx2/rng.c new file mode 120000 index 0000000..6e2fdac --- /dev/null +++ b/sha2-avx2/rng.c @@ -0,0 +1 @@ +../ref/rng.c \ No newline at end of file diff --git a/sha2-avx2/rng.h b/sha2-avx2/rng.h new file mode 120000 index 0000000..d678c7c --- /dev/null +++ b/sha2-avx2/rng.h @@ -0,0 +1 @@ +../ref/rng.h \ No newline at end of file diff --git a/sha2-avx2/sha2.c b/sha2-avx2/sha2.c new file mode 120000 index 0000000..7ba32d4 --- /dev/null +++ b/sha2-avx2/sha2.c @@ -0,0 +1 @@ +../ref/sha2.c \ No newline at end of file diff --git a/sha2-avx2/sha2.h b/sha2-avx2/sha2.h new file mode 120000 index 0000000..8c1ff67 --- /dev/null +++ b/sha2-avx2/sha2.h @@ -0,0 +1 @@ +../ref/sha2.h \ No newline at end of file diff --git a/sha2-avx2/sha256avx.c b/sha2-avx2/sha256avx.c new file mode 100644 index 0000000..7fc1091 --- /dev/null +++ b/sha2-avx2/sha256avx.c @@ -0,0 +1,294 @@ +#include +#include +#include + +#include "sha256avx.h" + +// Transpose 8 vectors containing 32-bit values +void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_init8x(sha256ctx *ctx) { + ctx->s[0] = _mm256_set_epi32(0x6a09e667,0x6a09e667,0x6a09e667,0x6a09e667,0x6a09e667,0x6a09e667,0x6a09e667,0x6a09e667); + ctx->s[1] = _mm256_set_epi32(0xbb67ae85,0xbb67ae85,0xbb67ae85,0xbb67ae85,0xbb67ae85,0xbb67ae85,0xbb67ae85,0xbb67ae85); + ctx->s[2] = _mm256_set_epi32(0x3c6ef372,0x3c6ef372,0x3c6ef372,0x3c6ef372,0x3c6ef372,0x3c6ef372,0x3c6ef372,0x3c6ef372); + ctx->s[3] = _mm256_set_epi32(0xa54ff53a,0xa54ff53a,0xa54ff53a,0xa54ff53a,0xa54ff53a,0xa54ff53a,0xa54ff53a,0xa54ff53a); + ctx->s[4] = _mm256_set_epi32(0x510e527f,0x510e527f,0x510e527f,0x510e527f,0x510e527f,0x510e527f,0x510e527f,0x510e527f); + ctx->s[5] = _mm256_set_epi32(0x9b05688c,0x9b05688c,0x9b05688c,0x9b05688c,0x9b05688c,0x9b05688c,0x9b05688c,0x9b05688c); + ctx->s[6] = _mm256_set_epi32(0x1f83d9ab,0x1f83d9ab,0x1f83d9ab,0x1f83d9ab,0x1f83d9ab,0x1f83d9ab,0x1f83d9ab,0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32(0x5be0cd19,0x5be0cd19,0x5be0cd19,0x5be0cd19,0x5be0cd19,0x5be0cd19,0x5be0cd19,0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) +{ + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64*i + curlen++] = 0x80; + while(curlen < 64) { + ctx->msgblocks[64*i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64*i + curlen++] = 0x80; + while(curlen < 64) { + ctx->msgblocks[64*i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64*0], + &ctx->msgblocks[64*1], + &ctx->msgblocks[64*2], + &ctx->msgblocks[64*3], + &ctx->msgblocks[64*4], + &ctx->msgblocks[64*5], + &ctx->msgblocks[64*6], + &ctx->msgblocks[64*7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64*i + 63] = ctx->msglen; + ctx->msgblocks[64*i + 62] = ctx->msglen >> 8; + ctx->msgblocks[64*i + 61] = ctx->msglen >> 16; + ctx->msgblocks[64*i + 60] = ctx->msglen >> 24; + ctx->msgblocks[64*i + 59] = ctx->msglen >> 32; + ctx->msgblocks[64*i + 58] = ctx->msglen >> 40; + ctx->msgblocks[64*i + 57] = ctx->msglen >> 48; + ctx->msgblocks[64*i + 56] = ctx->msglen >> 56; + } + sha256_transform8x(ctx, + &ctx->msgblocks[64*0], + &ctx->msgblocks[64*1], + &ctx->msgblocks[64*2], + &ctx->msgblocks[64*3], + &ctx->msgblocks[64*4], + &ctx->msgblocks[64*5], + &ctx->msgblocks[64*6], + &ctx->msgblocks[64*7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256ctx *ctx, + const unsigned char* data0, + const unsigned char* data1, + const unsigned char* data2, + const unsigned char* data3, + const unsigned char* data4, + const unsigned char* data5, + const unsigned char* data6, + const unsigned char* data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/sha2-avx2/sha256avx.h b/sha2-avx2/sha256avx.h new file mode 100644 index 0000000..e887063 --- /dev/null +++ b/sha2-avx2/sha256avx.h @@ -0,0 +1,96 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H +#include "immintrin.h" +#include + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - y)) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - y)) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32(RC[rc]), w); \ + d = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + h = ADD32(T0, T1); + +typedef struct SHA256state { + u256 s[8]; + unsigned char msgblocks[8*64]; + int datalen; + unsigned long long msglen; +} sha256ctx; + + +void transpose(u256 s[8]); +void sha256_init8x(sha256ctx *ctx); +void sha256_final8x(sha256ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +void sha256_transform8x(sha256ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/sha2-avx2/sha256x8.c b/sha2-avx2/sha256x8.c new file mode 100644 index 0000000..6f4f965 --- /dev/null +++ b/sha2-avx2/sha256x8.c @@ -0,0 +1,201 @@ +#include + +#include "sha256x8.h" +#include "sha256avx.h" +#include "utils.h" + +static uint32_t load_bigendian_32(const uint8_t *x) { + return (uint32_t)(x[3]) | (((uint32_t)(x[2])) << 8) | + (((uint32_t)(x[1])) << 16) | (((uint32_t)(x[0])) << 24); +} + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while(inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + int bytes_to_copy = inlen - i; + memcpy(&ctx->msgblocks[64*0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64*1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64*2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64*3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64*4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64*5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64*6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64*7], in7 + i, bytes_to_copy); + ctx->datalen = bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *seed, + unsigned long long seedlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + uint32_t t; + + sha256ctx ctx; + + for (size_t i = 0; i < 8; i++) { + t = load_bigendian_32(seed + 4*i); + ctx.s[i] = _mm256_set_epi32(t, t, t, t, t, t, t, t); + } + + ctx.datalen = 0; + ctx.msglen = seedlen; + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) +{ + sha256ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) +{ + SPX_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8*SPX_SHA256_OUTPUT_BYTES]; + unsigned long i; + unsigned int j; + + memcpy(inbufx8 + 0*(inlen + 4), in0, inlen); + memcpy(inbufx8 + 1*(inlen + 4), in1, inlen); + memcpy(inbufx8 + 2*(inlen + 4), in2, inlen); + memcpy(inbufx8 + 3*(inlen + 4), in3, inlen); + memcpy(inbufx8 + 4*(inlen + 4), in4, inlen); + memcpy(inbufx8 + 5*(inlen + 4), in5, inlen); + memcpy(inbufx8 + 6*(inlen + 4), in6, inlen); + memcpy(inbufx8 + 7*(inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i+1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j*(inlen + 4), i); + } + + sha256x8(outx8 + 0*outlen, + outx8 + 1*outlen, + outx8 + 2*outlen, + outx8 + 3*outlen, + outx8 + 4*outlen, + outx8 + 5*outlen, + outx8 + 6*outlen, + outx8 + 7*outlen, + inbufx8 + 0*(inlen + 4), + inbufx8 + 1*(inlen + 4), + inbufx8 + 2*(inlen + 4), + inbufx8 + 3*(inlen + 4), + inbufx8 + 4*(inlen + 4), + inbufx8 + 5*(inlen + 4), + inbufx8 + 6*(inlen + 4), + inbufx8 + 7*(inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j*(inlen + 4), i); + } + sha256x8(outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0*(inlen + 4), + inbufx8 + 1*(inlen + 4), + inbufx8 + 2*(inlen + 4), + inbufx8 + 3*(inlen + 4), + inbufx8 + 4*(inlen + 4), + inbufx8 + 5*(inlen + 4), + inbufx8 + 6*(inlen + 4), + inbufx8 + 7*(inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j*outlen, + outbufx8 + j*SPX_SHA256_OUTPUT_BYTES, + outlen - i*SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/sha2-avx2/sha256x8.h b/sha2-avx2/sha256x8.h new file mode 100644 index 0000000..0060de5 --- /dev/null +++ b/sha2-avx2/sha256x8.h @@ -0,0 +1,69 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal SPX_N */ + +#if SPX_SHA256_OUTPUT_BYTES < SPX_N + #error Linking against SHA-256 with N larger than 32 bytes is not supported +#endif + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *seed, + unsigned long long seedlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/sha2-avx2/sha2_offsets.h b/sha2-avx2/sha2_offsets.h new file mode 120000 index 0000000..ca63278 --- /dev/null +++ b/sha2-avx2/sha2_offsets.h @@ -0,0 +1 @@ +../ref/sha2_offsets.h \ No newline at end of file diff --git a/sha2-avx2/sha512x4.c b/sha2-avx2/sha512x4.c new file mode 100644 index 0000000..3eaa0f6 --- /dev/null +++ b/sha2-avx2/sha512x4.c @@ -0,0 +1,462 @@ +#include +#include +#include + +#define SPX_SHA512_OUTPUT_BYTES 64 /* In sha256.h, but we don't want to */ + /* pull in the entire thing */ +#include "sha512x4.h" +#include "utils.h" + +typedef uint64_t u64; +typedef __m256i u256; + +static void sha512_transform4x( + sha512ctx4x *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3 +); + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +// Transpose 4 vectors containing 64-bit values +// That is, it rearranges the array: +// A B C D +// E F G H +// I J K L +// M N O P +// into +// A E I M +// B F J N +// C G K O +// D H L P +// where each letter stands for 64 bits (and lsbits on the left) +static void transpose(u256 s[4]) { + u256 tmp[4]; + tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); + tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); + tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); + tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); + // tmp is in the order of + // A E C G + // B F D H + // I M K O + // J N L P + s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); + s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); + s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); + s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); +} + + +static void sha512_init4x(sha512ctx4x *ctx) { +#define SET4(x) _mm256_set_epi64x(x, x, x, x) + ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); + ctx->s[1] = SET4(0xbb67ae8584caa73bULL); + ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); + ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); + ctx->s[4] = SET4(0x510e527fade682d1ULL); + ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); + ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); + ctx->s[7] = SET4(0x5be0cd19137e2179ULL); +#undef SET4 + + ctx->datalen = 0; + ctx->msglen = 0; +} + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD64 _mm256_add_epi64 + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) + +#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) +#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) + +#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - y)) + +static u256 XOR3(u256 a, u256 b, u256 c) { + return XOR(XOR(a, b), c); +} + +#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) +#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) +#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) + +static u256 MAJ_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(XOR(a, c), XOR(b, c))); +} +static u256 CH_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(a, XOR(b, c))); +} +static u256 SIGMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); +} +static u256 SIGMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); +} +static u256 GAMMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); +} +static u256 GAMMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); +} + +#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x(RC[rc])); \ + T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + d = ADD64(d, T0); \ + h = ADD64(T0, T1); + +static const unsigned long long RC[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +static void sha512_transform4x( + sha512ctx4x *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3) { + u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; + + // Load words and transform data correctly + w[0 ] = BYTESWAP(LOAD(d0 )); + w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); + w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); + w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); + + w[1 ] = BYTESWAP(LOAD(d1 )); + w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); + w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); + w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); + + w[2 ] = BYTESWAP(LOAD(d2 )); + w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); + w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); + w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); + + w[3 ] = BYTESWAP(LOAD(d3 )); + w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); + w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); + w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); + + transpose(w); + transpose(w + 4); + transpose(w + 8); + transpose(w + 12); + + // Initial State + s0 = ctx->s[0]; + s1 = ctx->s[1]; + s2 = ctx->s[2]; + s3 = ctx->s[3]; + s4 = ctx->s[4]; + s5 = ctx->s[5]; + s6 = ctx->s[6]; + s7 = ctx->s[7]; + + // The first 16 rounds (where the w inputs are directly from the data) + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); + +#define M(i) (((i)+16) & 0xf) +#define NextW(i) \ + w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); + + // The remaining 64 rounds (where the w inputs are a linear fix of the data) + for (unsigned i = 16; i<80; i+=16) { + nw = NextW(0); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i+0, nw); + nw = NextW(1); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i+1, nw); + nw = NextW(2); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i+2, nw); + nw = NextW(3); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i+3, nw); + nw = NextW(4); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i+4, nw); + nw = NextW(5); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i+5, nw); + nw = NextW(6); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i+6, nw); + nw = NextW(7); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i+7, nw); + nw = NextW(8); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i+8, nw); + nw = NextW(9); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i+9, nw); + nw = NextW(10); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i+10, nw); + nw = NextW(11); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i+11, nw); + nw = NextW(12); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i+12, nw); + nw = NextW(13); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i+13, nw); + nw = NextW(14); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i+14, nw); + nw = NextW(15); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i+15, nw); + } + + // Feed Forward + ctx->s[0] = ADD64(s0, ctx->s[0]); + ctx->s[1] = ADD64(s1, ctx->s[1]); + ctx->s[2] = ADD64(s2, ctx->s[2]); + ctx->s[3] = ADD64(s3, ctx->s[3]); + ctx->s[4] = ADD64(s4, ctx->s[4]); + ctx->s[5] = ADD64(s5, ctx->s[5]); + ctx->s[6] = ADD64(s6, ctx->s[6]); + ctx->s[7] = ADD64(s7, ctx->s[7]); +} + +static void _sha512x4( + sha512ctx4x* ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + unsigned int i = 0; + + while(inlen - i >= 128) { + sha512_transform4x( + ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i + ); + ctx->msglen += 1024; + i += 128; + } + + ctx->datalen = inlen - i; + memcpy(&ctx->msgblocks[128*0], in0 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128*1], in1 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128*2], in2 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128*3], in3 + i, ctx->datalen); + + // Padding + unsigned long curlen; + if (ctx->datalen < 112) { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128*i + curlen++] = 0x80; + while(curlen < 128) { + ctx->msgblocks[128*i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128*i + curlen++] = 0x80; + while(curlen < 128) { + ctx->msgblocks[128*i + curlen++] = 0x00; + } + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + memset(ctx->msgblocks, 0, 4 * 128); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 4; i++) { + ctx->msgblocks[128*i + 127] = ctx->msglen; + ctx->msgblocks[128*i + 126] = ctx->msglen >> 8; + ctx->msgblocks[128*i + 125] = ctx->msglen >> 16; + ctx->msgblocks[128*i + 124] = ctx->msglen >> 24; + ctx->msgblocks[128*i + 123] = ctx->msglen >> 32; + ctx->msgblocks[128*i + 122] = ctx->msglen >> 40; + ctx->msgblocks[128*i + 121] = ctx->msglen >> 48; + ctx->msgblocks[128*i + 120] = ctx->msglen >> 56; + memset( &ctx->msgblocks[128*i + 112], 0, 8 ); + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + + // Compute final hash output + transpose(ctx->s); + transpose(ctx->s+4); + + // Store Hash value + __m256i out[2]; + STORE(out, BYTESWAP(ctx->s[0])); + STORE(out+1, BYTESWAP(ctx->s[4])); + memcpy(out0, out, 64); + + STORE(out, BYTESWAP(ctx->s[1])); + STORE(out+1, BYTESWAP(ctx->s[5])); + memcpy(out1, out, 64); + + STORE(out, BYTESWAP(ctx->s[2])); + STORE(out+1, BYTESWAP(ctx->s[6])); + memcpy(out2, out, 64); + + STORE(out, BYTESWAP(ctx->s[3])); + STORE(out+1, BYTESWAP(ctx->s[7])); + memcpy(out3, out, 64); +} + + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen) +{ + SPX_VLA(unsigned char, inbufx4, 4*(inlen + 4)); + unsigned char outbuf[4*64]; + unsigned long i; + unsigned int j; + + memcpy(inbufx4 + 0*(inlen + 4), in0, inlen); + memcpy(inbufx4 + 1*(inlen + 4), in1, inlen); + memcpy(inbufx4 + 2*(inlen + 4), in2, inlen); + memcpy(inbufx4 + 3*(inlen + 4), in3, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + unsigned long remaining = outlen; + for (i = 0; remaining > 0; i++) { + unsigned this_step = SPX_SHA512_OUTPUT_BYTES; + if (this_step > remaining) this_step = remaining; + remaining -= this_step; + for (j = 0; j < 4; j++) { + u32_to_bytes(inbufx4 + inlen + j*(inlen + 4), i); + } + + sha512ctx4x ctx; + sha512_init4x(&ctx); + + _sha512x4( + &ctx, + outbuf + 0*64, + outbuf + 1*64, + outbuf + 2*64, + outbuf + 3*64, + inbufx4 + 0*(inlen + 4), + inbufx4 + 1*(inlen + 4), + inbufx4 + 2*(inlen + 4), + inbufx4 + 3*(inlen + 4), + inlen+4 + ); + + memcpy(outx4 + 0*outlen, outbuf+0*64, this_step); + memcpy(outx4 + 1*outlen, outbuf+1*64, this_step); + memcpy(outx4 + 2*outlen, outbuf+2*64, this_step); + memcpy(outx4 + 3*outlen, outbuf+3*64, this_step); + outx4 += this_step; + } +} + +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *seed, + unsigned long long seedlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + sha512ctx4x ctx; + unsigned long i; + + for (i = 0; i < 8; i++) { + uint64_t t = (uint64_t)(seed[7]) | (((uint64_t)(seed[6])) << 8) | + (((uint64_t)(seed[5])) << 16) | (((uint64_t)(seed[4])) << 24) | + (((uint64_t)(seed[3])) << 32) | (((uint64_t)(seed[2])) << 40) | + (((uint64_t)(seed[1])) << 48) | (((uint64_t)(seed[0])) << 56); + ctx.s[i] = _mm256_set_epi64x(t, t, t, t); + seed += 8; + } + + ctx.msglen = seedlen; + _sha512x4( + &ctx, + out0, out1, out2, out3, + in0, in1, in2, in3, + inlen + ); +} diff --git a/sha2-avx2/sha512x4.h b/sha2-avx2/sha512x4.h new file mode 100644 index 0000000..013459f --- /dev/null +++ b/sha2-avx2/sha512x4.h @@ -0,0 +1,44 @@ +#ifndef SHA512AVX_H +#define SHA512AVX_H +#include +#include "immintrin.h" + +#include "params.h" + +typedef struct SHA512state4x { + __m256i s[8]; + unsigned char msgblocks[4*128]; + int datalen; + unsigned long long msglen; +} sha512ctx4x; + + +#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *seed, + unsigned long long seedlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen); + + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen); + +#endif diff --git a/sha2-avx2/sign.c b/sha2-avx2/sign.c new file mode 120000 index 0000000..42fea88 --- /dev/null +++ b/sha2-avx2/sign.c @@ -0,0 +1 @@ +../ref/sign.c \ No newline at end of file diff --git a/sha2-avx2/test/benchmark.c b/sha2-avx2/test/benchmark.c new file mode 100644 index 0000000..a65bd62 --- /dev/null +++ b/sha2-avx2/test/benchmark.c @@ -0,0 +1,162 @@ +#define _POSIX_C_SOURCE 199309L + +#include +#include +#include + +#include "../api.h" +#include "../fors.h" +#include "../wots.h" +#include "../wotsx8.h" +#include "../params.h" +#include "../randombytes.h" + +#define SPX_MLEN 32 +#define NTESTS 10 + +static void wots_gen_pkx8(unsigned char *pk, const spx_ctx *ctx, + uint32_t addr[8]); + +static int cmp_llu(const void *a, const void*b) +{ + if(*(unsigned long long *)a < *(unsigned long long *)b) return -1; + if(*(unsigned long long *)a > *(unsigned long long *)b) return 1; + return 0; +} + +static unsigned long long median(unsigned long long *l, size_t llen) +{ + qsort(l,llen,sizeof(unsigned long long),cmp_llu); + + if(llen%2) return l[llen/2]; + else return (l[llen/2-1]+l[llen/2])/2; +} + +static void delta(unsigned long long *l, size_t llen) +{ + unsigned int i; + for(i = 0; i < llen - 1; i++) { + l[i] = l[i+1] - l[i]; + } +} + +static unsigned long long cpucycles(void) +{ + unsigned long long result; + __asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax" + : "=a" (result) :: "%rdx"); + return result; +} + +static void printfcomma (unsigned long long n) +{ + if (n < 1000) { + printf("%llu", n); + return; + } + printfcomma(n / 1000); + printf (",%03llu", n % 1000); +} + +static void printfalignedcomma (unsigned long long n, int len) +{ + unsigned long long ncopy = n; + int i = 0; + + while (ncopy > 9) { + len -= 1; + ncopy /= 10; + i += 1; // to account for commas + } + i = i/3 - 1; // to account for commas + for (; i < len; i++) { + printf(" "); + } + printfcomma(n); +} + +static void display_result(double result, unsigned long long *l, size_t llen, unsigned long long mul) +{ + unsigned long long med; + + result /= NTESTS; + delta(l, NTESTS + 1); + med = median(l, llen); + printf("avg. %11.2lf us (%2.2lf sec); median ", result, result / 1e6); + printfalignedcomma(med, 12); + printf(" cycles, %5llux: ", mul); + printfalignedcomma(mul*med, 12); + printf(" cycles\n"); +} + +#define MEASURE(TEXT, MUL, FNCALL)\ + printf(TEXT);\ + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);\ + for(i = 0; i < NTESTS; i++) {\ + t[i] = cpucycles();\ + FNCALL;\ + }\ + t[NTESTS] = cpucycles();\ + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop);\ + result = (stop.tv_sec - start.tv_sec) * 1e6 + (stop.tv_nsec - start.tv_nsec) / 1e3;\ + display_result(result, t, NTESTS, MUL); + +int main(void) +{ + /* Make stdout buffer more responsive. */ + setbuf(stdout, NULL); + + spx_ctx ctx; + unsigned char pk[SPX_PK_BYTES]; + unsigned char sk[SPX_SK_BYTES]; + unsigned char *m = malloc(SPX_MLEN); + unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); + unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); + + unsigned char fors_pk[SPX_FORS_PK_BYTES]; + unsigned char fors_m[SPX_FORS_MSG_BYTES]; + unsigned char fors_sig[SPX_FORS_BYTES]; + unsigned char addr[SPX_ADDR_BYTES]; + unsigned char wots_pk[8*SPX_WOTS_PK_BYTES]; + + unsigned long long smlen; + unsigned long long mlen; + unsigned long long t[NTESTS+1]; + struct timespec start, stop; + double result; + int i; + + randombytes(m, SPX_MLEN); + randombytes(addr, SPX_ADDR_BYTES); + + printf("Parameters: n = %d, h = %d, d = %d, b = %d, k = %d, w = %d\n", + SPX_N, SPX_FULL_HEIGHT, SPX_D, SPX_FORS_HEIGHT, SPX_FORS_TREES, + SPX_WOTS_W); + + printf("Running %d iterations.\n", NTESTS); + + MEASURE("Generating keypair.. ", 1, crypto_sign_keypair(pk, sk)); + MEASURE(" - WOTS pk gen 8x.. ", (1 << SPX_TREE_HEIGHT) / 8, wots_gen_pkx8(wots_pk, &ctx, (uint32_t *) addr)); + MEASURE("Signing.. ", 1, crypto_sign(sm, &smlen, m, SPX_MLEN, sk)); + MEASURE(" - FORS signing.. ", 1, fors_sign(fors_sig, fors_pk, fors_m, &ctx, (uint32_t *) addr)); + MEASURE(" - WOTS pk gen x8.. ", SPX_D * (1 << SPX_TREE_HEIGHT) / 8, wots_gen_pkx8(wots_pk, &ctx, (uint32_t *) addr)); + MEASURE("Verifying.. ", 1, crypto_sign_open(mout, &mlen, sm, smlen, pk)); + + printf("Signature size: %d (%.2f KiB)\n", SPX_BYTES, SPX_BYTES / 1024.0); + printf("Public key size: %d (%.2f KiB)\n", SPX_PK_BYTES, SPX_PK_BYTES / 1024.0); + printf("Secret key size: %d (%.2f KiB)\n", SPX_SK_BYTES, SPX_SK_BYTES / 1024.0); + + free(m); + free(sm); + free(mout); + + return 0; +} + +static void wots_gen_pkx8(unsigned char *pk, const spx_ctx *ctx, + uint32_t addr[8]) { + struct leaf_info_x8 leaf; + unsigned steps[ SPX_WOTS_LEN ] = { 0 }; + INITIALIZE_LEAF_INFO_X8(leaf, addr, steps); + wots_gen_leafx8(pk, ctx, 0, &leaf); +} diff --git a/sha2-avx2/test/fors.c b/sha2-avx2/test/fors.c new file mode 120000 index 0000000..b2bccee --- /dev/null +++ b/sha2-avx2/test/fors.c @@ -0,0 +1 @@ +../../ref/test/fors.c \ No newline at end of file diff --git a/sha2-avx2/test/spx.c b/sha2-avx2/test/spx.c new file mode 120000 index 0000000..7af26df --- /dev/null +++ b/sha2-avx2/test/spx.c @@ -0,0 +1 @@ +../../ref/test/spx.c \ No newline at end of file diff --git a/sha2-avx2/test/thashx8.c b/sha2-avx2/test/thashx8.c new file mode 100644 index 0000000..37d27c3 --- /dev/null +++ b/sha2-avx2/test/thashx8.c @@ -0,0 +1,94 @@ +#include +#include + +#include "../thashx8.h" +#include "../thash.h" +#include "../randombytes.h" +#include "../params.h" +#include "../hash.h" + +#if SPX_SHA512 +#include "../sha2.h" +#include "../sha512x4.h" +#endif + + +int main(void) +{ + /* Make stdout buffer more responsive. */ + setbuf(stdout, NULL); + + unsigned char input[16*SPX_N]; + spx_ctx ctx; + unsigned char output[8*SPX_N]; + unsigned char out8[8*SPX_N]; + uint32_t addr[8*8] = {0}; + unsigned int j; + + randombytes(ctx.pub_seed, SPX_N); + randombytes(input, 16*SPX_N); + randombytes((unsigned char *)addr, 8 * 8 * sizeof(uint32_t)); + + initialize_hash_function(&ctx); + + printf("Testing if thash matches thashx8 on one block ... "); + + for (j = 0; j < 8; j++) { + thash(out8 + j * SPX_N, input + j * SPX_N, 1, &ctx, addr + j*8); + } + + thashx8(output + 0*SPX_N, + output + 1*SPX_N, + output + 2*SPX_N, + output + 3*SPX_N, + output + 4*SPX_N, + output + 5*SPX_N, + output + 6*SPX_N, + output + 7*SPX_N, + input + 0*SPX_N, + input + 1*SPX_N, + input + 2*SPX_N, + input + 3*SPX_N, + input + 4*SPX_N, + input + 5*SPX_N, + input + 6*SPX_N, + input + 7*SPX_N, + 1, &ctx, addr); + + if (memcmp(out8, output, 8 * SPX_N)) { + printf("failed!\n"); + return -1; + } + printf("successful.\n"); + + printf("Testing if thash matches thashx8 on two blocks ... "); + + for (j = 0; j < 8; j++) { + thash(out8 + j * SPX_N, input + (2*j) * SPX_N, 2, &ctx, addr + j*8); + } + + thashx8(output + 0*SPX_N, + output + 1*SPX_N, + output + 2*SPX_N, + output + 3*SPX_N, + output + 4*SPX_N, + output + 5*SPX_N, + output + 6*SPX_N, + output + 7*SPX_N, + input + 0*SPX_N, + input + 2*SPX_N, + input + 4*SPX_N, + input + 6*SPX_N, + input + 8*SPX_N, + input + 10*SPX_N, + input + 12*SPX_N, + input + 14*SPX_N, + 2, &ctx, addr); + + if (memcmp(out8, output, 8 * SPX_N)) { + printf("failed!\n"); + return -1; + } + printf("successful.\n"); + return 0; +} diff --git a/sha2-avx2/thash.h b/sha2-avx2/thash.h new file mode 120000 index 0000000..937dd48 --- /dev/null +++ b/sha2-avx2/thash.h @@ -0,0 +1 @@ +../ref/thash.h \ No newline at end of file diff --git a/sha2-avx2/thash_sha2_robust.c b/sha2-avx2/thash_sha2_robust.c new file mode 120000 index 0000000..60e5139 --- /dev/null +++ b/sha2-avx2/thash_sha2_robust.c @@ -0,0 +1 @@ +../ref/thash_sha2_robust.c \ No newline at end of file diff --git a/sha2-avx2/thash_sha2_robustx8.c b/sha2-avx2/thash_sha2_robustx8.c new file mode 100644 index 0000000..8700d90 --- /dev/null +++ b/sha2-avx2/thash_sha2_robustx8.c @@ -0,0 +1,276 @@ +#include +#include + +#include "address.h" +#include "utils.h" +#include "params.h" +#include "thashx8.h" +#include "sha2.h" +#include "sha256x8.h" +#include "sha256avx.h" + +#if SPX_SHA512 +#include "sha512x4.h" + +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8*8] +); +#endif + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8*8]) +{ +#if SPX_SHA512 + if (inblocks > 1) { + thashx8_512( + out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, + inblocks, ctx, addrx8); + return; + } +#endif + SPX_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)); + SPX_VLA(unsigned char, outbufx8, 8 * SPX_SHA256_OUTPUT_BYTES); + SPX_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + addrx8 + i*8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x8(bitmaskx8, inblocks * SPX_N, + bufx8 + 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in0[i] ^ bitmaskx8[i + 0*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in1[i] ^ bitmaskx8[i + 1*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in2[i] ^ bitmaskx8[i + 2*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in3[i] ^ bitmaskx8[i + 3*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in4[i] ^ bitmaskx8[i + 4*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in5[i] ^ bitmaskx8[i + 5*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in6[i] ^ bitmaskx8[i + 6*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in7[i] ^ bitmaskx8[i + 7*(inblocks * SPX_N)]; + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + ctx->state_seeded, 512, + + /* in */ + bufx8 + SPX_N + 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + +#if SPX_SHA512 +/** + * 2x4-way parallel version of thash; this is for the uses of thash that are + * based on SHA-512 + */ +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8*8]) +{ + SPX_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + SPX_VLA(unsigned char, outbuf, 4 * SPX_SHA512_OUTPUT_BYTES); + SPX_VLA(unsigned char, bitmaskx4, 4 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + addrx8 + i*8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x4_512(bitmaskx4, inblocks * SPX_N, + bufx8 + 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in0[i] ^ bitmaskx4[i + 0*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in1[i] ^ bitmaskx4[i + 1*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in2[i] ^ bitmaskx4[i + 2*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in3[i] ^ bitmaskx4[i + 3*(inblocks * SPX_N)]; + } + + mgf1x4_512(bitmaskx4, inblocks * SPX_N, + bufx8 + 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in4[i] ^ bitmaskx4[i + 0*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in5[i] ^ bitmaskx4[i + 1*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in6[i] ^ bitmaskx4[i + 2*(inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)] = + in7[i] ^ bitmaskx4[i + 3*(inblocks * SPX_N)]; + } + + sha512x4_seeded( + outbuf + 0*SPX_SHA512_OUTPUT_BYTES, + outbuf + 1*SPX_SHA512_OUTPUT_BYTES, + outbuf + 2*SPX_SHA512_OUTPUT_BYTES, + outbuf + 3*SPX_SHA512_OUTPUT_BYTES, + ctx->state_seeded_512, /* seed */ + 1024, /* seed length */ + bufx8 + SPX_N + 0*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 1*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 2*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 3*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ + ); + + memcpy(out0, outbuf + 0*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbuf + 1*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbuf + 2*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbuf + 3*SPX_SHA512_OUTPUT_BYTES, SPX_N); + + sha512x4_seeded( + outbuf + 0*SPX_SHA512_OUTPUT_BYTES, + outbuf + 1*SPX_SHA512_OUTPUT_BYTES, + outbuf + 2*SPX_SHA512_OUTPUT_BYTES, + outbuf + 3*SPX_SHA512_OUTPUT_BYTES, + ctx->state_seeded_512, /* seed */ + 1024, /* seed length */ + bufx8 + SPX_N + 4*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 5*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 6*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + SPX_N + 7*(SPX_N + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ + ); + + memcpy(out4, outbuf + 0*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbuf + 1*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbuf + 2*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbuf + 3*SPX_SHA512_OUTPUT_BYTES, SPX_N); +} +#endif diff --git a/sha2-avx2/thash_sha2_simple.c b/sha2-avx2/thash_sha2_simple.c new file mode 120000 index 0000000..c87305c --- /dev/null +++ b/sha2-avx2/thash_sha2_simple.c @@ -0,0 +1 @@ +../ref/thash_sha2_simple.c \ No newline at end of file diff --git a/sha2-avx2/thash_sha2_simplex8.c b/sha2-avx2/thash_sha2_simplex8.c new file mode 100644 index 0000000..2b40d02 --- /dev/null +++ b/sha2-avx2/thash_sha2_simplex8.c @@ -0,0 +1,220 @@ +#include +#include + +#include "address.h" +#include "utils.h" +#include "params.h" +#include "thashx8.h" +#include "sha2.h" +#include "sha256x8.h" +#include "sha256avx.h" + +#if SPX_SHA512 +#include "sha512x4.h" + +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8*8] +); +#endif + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8*8]) +{ +#if SPX_SHA512 + if (inblocks > 1) { + thashx8_512( + out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, + inblocks, ctx, addrx8); + return; + } +#endif + unsigned char bufx8[8*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)]; + unsigned char outbufx8[8*SPX_SHA256_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + addrx8 + i*8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in7, inblocks * SPX_N); + + sha256x8_seeded( + /* out */ + outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + ctx->state_seeded, 512, + + /* in */ + bufx8 + 0*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 1*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 2*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 3*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 4*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 5*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 6*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 7*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6*SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7*SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + +#if SPX_SHA512 +/** + * 2x4-way parallel version of thash; this is for the uses of thash that are + * based on SHA-512 + */ +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8*8]) +{ + unsigned char bufx8[8*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N)]; + unsigned char outbuf[4*SPX_SHA512_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + addrx8 + i*8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), in7, inblocks * SPX_N); + + sha512x4_seeded( + outbuf + 0*SPX_SHA512_OUTPUT_BYTES, + outbuf + 1*SPX_SHA512_OUTPUT_BYTES, + outbuf + 2*SPX_SHA512_OUTPUT_BYTES, + outbuf + 3*SPX_SHA512_OUTPUT_BYTES, + ctx->state_seeded_512, /* seed */ + 1024, /* seed length */ + bufx8 + 0*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), /* in */ + bufx8 + 1*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 2*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 3*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ + ); + + memcpy(out0, outbuf + 0*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbuf + 1*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbuf + 2*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbuf + 3*SPX_SHA512_OUTPUT_BYTES, SPX_N); + + sha512x4_seeded( + outbuf + 0*SPX_SHA512_OUTPUT_BYTES, + outbuf + 1*SPX_SHA512_OUTPUT_BYTES, + outbuf + 2*SPX_SHA512_OUTPUT_BYTES, + outbuf + 3*SPX_SHA512_OUTPUT_BYTES, + ctx->state_seeded_512, /* seed */ + 1024, /* seed length */ + bufx8 + 4*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), /* in */ + bufx8 + 5*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 6*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + bufx8 + 7*(SPX_SHA256_ADDR_BYTES + inblocks*SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks*SPX_N /* len */ + ); + + memcpy(out4, outbuf + 0*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbuf + 1*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbuf + 2*SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbuf + 3*SPX_SHA512_OUTPUT_BYTES, SPX_N); +} +#endif diff --git a/sha2-avx2/thashx8.h b/sha2-avx2/thashx8.h new file mode 100644 index 0000000..d6bf618 --- /dev/null +++ b/sha2-avx2/thashx8.h @@ -0,0 +1,27 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8*8]); + +#endif diff --git a/sha2-avx2/utils.c b/sha2-avx2/utils.c new file mode 120000 index 0000000..e8ef6eb --- /dev/null +++ b/sha2-avx2/utils.c @@ -0,0 +1 @@ +../ref/utils.c \ No newline at end of file diff --git a/sha2-avx2/utils.h b/sha2-avx2/utils.h new file mode 120000 index 0000000..51b0d39 --- /dev/null +++ b/sha2-avx2/utils.h @@ -0,0 +1 @@ +../ref/utils.h \ No newline at end of file diff --git a/sha2-avx2/utilsx8.c b/sha2-avx2/utilsx8.c new file mode 100644 index 0000000..af21cf5 --- /dev/null +++ b/sha2-avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" +#include "params.h" +#include "thashx8.h" +#include "address.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char* /* Where to write the leaves */, + const spx_ctx*, + uint32_t idx, void *info), + uint32_t tree_addrx8[8*8], + void *info) +{ + /* This is where we keep the intermediate nodes */ + SPX_VLA(unsigned char, stackx8, 8 * tree_height * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height-3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8*SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8*idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h=0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7*SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 8 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7*SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf&7)^1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j*8, h + 1); + set_tree_index(tree_addrx8 + j*8, + (8/2) * (internal_idx&~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/sha2-avx2/utilsx8.h b/sha2-avx2/utilsx8.h new file mode 100644 index 0000000..ca42146 --- /dev/null +++ b/sha2-avx2/utilsx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char* /* Where to write the leaves */, + const spx_ctx* /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8*8], void *info); + +#endif diff --git a/sha2-avx2/wots.c b/sha2-avx2/wots.c new file mode 100644 index 0000000..779a868 --- /dev/null +++ b/sha2-avx2/wots.c @@ -0,0 +1,293 @@ +#include +#include + +#include "utils.h" +#include "utilsx8.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "wots.h" +#include "wotsx8.h" +#include "address.h" +#include "params.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) +{ + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8*8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs+j*8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN*SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i+j < SPX_WOTS_LEN; j++) { + idx = idxs[i+j]; + set_chain_addr(addrs+j*8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i+watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs+j*8, k + start[idxs[i+j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) +{ + int in = 0; + int out = 0; + unsigned char total; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) +{ + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) +{ + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) +{ + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j*8, leaf_idx + j ); + set_keypair_addr( pk_addr + j*8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j*8, i); + set_hash_addr(leaf_addr + j*8, 0); + set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0*wots_offset, + buffer + 1*wots_offset, + buffer + 2*wots_offset, + buffer + 3*wots_offset, + buffer + 4*wots_offset, + buffer + 5*wots_offset, + buffer + 6*wots_offset, + buffer + 7*wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k=0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index*wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) break; + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j*8, k); + } + thashx8(buffer + 0*wots_offset, + buffer + 1*wots_offset, + buffer + 2*wots_offset, + buffer + 3*wots_offset, + buffer + 4*wots_offset, + buffer + 5*wots_offset, + buffer + 6*wots_offset, + buffer + 7*wots_offset, + buffer + 0*wots_offset, + buffer + 1*wots_offset, + buffer + 2*wots_offset, + buffer + 3*wots_offset, + buffer + 4*wots_offset, + buffer + 5*wots_offset, + buffer + 6*wots_offset, + buffer + 7*wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0*SPX_N, + dest + 1*SPX_N, + dest + 2*SPX_N, + dest + 3*SPX_N, + dest + 4*SPX_N, + dest + 5*SPX_N, + dest + 6*SPX_N, + dest + 7*SPX_N, + pk_buffer + 0*wots_offset, + pk_buffer + 1*wots_offset, + pk_buffer + 2*wots_offset, + pk_buffer + 3*wots_offset, + pk_buffer + 4*wots_offset, + pk_buffer + 5*wots_offset, + pk_buffer + 6*wots_offset, + pk_buffer + 7*wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/sha2-avx2/wots.h b/sha2-avx2/wots.h new file mode 120000 index 0000000..8c327ea --- /dev/null +++ b/sha2-avx2/wots.h @@ -0,0 +1 @@ +../ref/wots.h \ No newline at end of file diff --git a/sha2-avx2/wotsx8.h b/sha2-avx2/wotsx8.h new file mode 100644 index 0000000..10f72ad --- /dev/null +++ b/sha2-avx2/wotsx8.h @@ -0,0 +1,40 @@ +#if !defined( WOTSX8_H_ ) +#define WOTSX8_H_ + +#include +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8*8]; + uint32_t pk_addr[8*8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + info.wots_sig = 0; \ + info.wots_sign_leaf = ~0; \ + info.wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &info.leaf_addr[8*i], addr, 32 ); \ + memcpy( &info.pk_addr[8*i], addr, 32 ); \ + } \ +} + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/shake-a64/.gitignore b/shake-a64/.gitignore new file mode 100644 index 0000000..67bcef9 --- /dev/null +++ b/shake-a64/.gitignore @@ -0,0 +1,5 @@ +test/* +!test/*.c +PQCsignKAT_*.rsp +PQCsignKAT_*.req +PQCgenKAT_sign diff --git a/shake-a64/Makefile b/shake-a64/Makefile new file mode 100644 index 0000000..d3b566a --- /dev/null +++ b/shake-a64/Makefile @@ -0,0 +1,49 @@ +PARAMS = sphincs-shake-128f +THASH = robust + +CFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3 -std=c99 -fomit-frame-pointer -flto -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) + +SOURCES = hash_shake.c hash_shakex2.c thash_shake_$(THASH)x2.c address.c randombytes.c merkle.c wots.c utils.c utilsx2.c fors.c sign.c fips202.c fips202x2.c f1600x2_const.c f1600x2.s +HEADERS = params.h hash.h hashx2.h thashx2.h address.h randombytes.h merkle.h wots.h utils.h utilsx2.h fors.h api.h fips202.h fips202x2.h f1600x2.h thash.h + +DET_SOURCES = $(SOURCES:randombytes.%=rng.%) +DET_HEADERS = $(HEADERS:randombytes.%=rng.%) + +TESTS = test/fors \ + test/spx \ + test/thashx2 \ + +BENCHMARK = test/benchmark + +.PHONY: clean test benchmark + +default: PQCgenKAT_sign + +all: PQCgenKAT_sign tests benchmarks + +tests: $(TESTS) + +test: $(TESTS:=.exec) + +benchmarks: $(BENCHMARK) + +benchmark: $(BENCHMARK:=.exec) + +PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) + $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto + +test/benchmark: test/benchmark.c test/cycles.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -o $@ test/cycles.c $(SOURCES) $< $(LDLIBS) + +test/%: test/%.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) + +test/%.exec: test/% + @$< + +clean: + -$(RM) $(TESTS) + -$(RM) $(BENCHMARK) + -$(RM) PQCgenKAT_sign + -$(RM) PQCsignKAT_*.rsp + -$(RM) PQCsignKAT_*.req diff --git a/shake-a64/PQCgenKAT_sign.c b/shake-a64/PQCgenKAT_sign.c new file mode 120000 index 0000000..a17dbe2 --- /dev/null +++ b/shake-a64/PQCgenKAT_sign.c @@ -0,0 +1 @@ +../ref/PQCgenKAT_sign.c \ No newline at end of file diff --git a/shake-a64/address.c b/shake-a64/address.c new file mode 120000 index 0000000..02c52c6 --- /dev/null +++ b/shake-a64/address.c @@ -0,0 +1 @@ +../ref/address.c \ No newline at end of file diff --git a/shake-a64/address.h b/shake-a64/address.h new file mode 120000 index 0000000..e670da5 --- /dev/null +++ b/shake-a64/address.h @@ -0,0 +1 @@ +../ref/address.h \ No newline at end of file diff --git a/shake-a64/api.h b/shake-a64/api.h new file mode 120000 index 0000000..ea89e0a --- /dev/null +++ b/shake-a64/api.h @@ -0,0 +1 @@ +../ref/api.h \ No newline at end of file diff --git a/shake-a64/context.h b/shake-a64/context.h new file mode 100644 index 0000000..993c9ce --- /dev/null +++ b/shake-a64/context.h @@ -0,0 +1,13 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#endif diff --git a/shake-a64/f1600x2.h b/shake-a64/f1600x2.h new file mode 100644 index 0000000..70c5a8e --- /dev/null +++ b/shake-a64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t* a, uint64_t* rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/shake-a64/f1600x2.s b/shake-a64/f1600x2.s new file mode 100644 index 0000000..640ed79 --- /dev/null +++ b/shake-a64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/shake-a64/f1600x2_const.c b/shake-a64/f1600x2_const.c new file mode 100644 index 0000000..6880176 --- /dev/null +++ b/shake-a64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/shake-a64/fips202.c b/shake-a64/fips202.c new file mode 120000 index 0000000..da2fa42 --- /dev/null +++ b/shake-a64/fips202.c @@ -0,0 +1 @@ +../ref/fips202.c \ No newline at end of file diff --git a/shake-a64/fips202.h b/shake-a64/fips202.h new file mode 120000 index 0000000..c759415 --- /dev/null +++ b/shake-a64/fips202.h @@ -0,0 +1 @@ +../ref/fips202.h \ No newline at end of file diff --git a/shake-a64/fips202x2.c b/shake-a64/fips202x2.c new file mode 100644 index 0000000..87c0df8 --- /dev/null +++ b/shake-a64/fips202x2.c @@ -0,0 +1,165 @@ +#include +#include + +#include "fips202x2.h" +#include "fips202.h" +#include "f1600x2.h" + +uint64_t load64(const unsigned char *x) +{ + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) +{ + unsigned int i; + + for(i=0; i<8; ++i) { + x[i] = u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) +{ + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) + { + for (i = 0; i < r / 8; ++i) + { + s[2*i+0] ^= load64(m0 + 8 * i); + s[2*i+1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) + { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) + { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) + { + s[2*i+0] ^= load64(t0 + 8 * i); + s[2*i+1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) +{ + unsigned int i; + + while(nblocks > 0) + { + f1600x2(s); + for(i=0;i<(r>>3);i++) + { + store64(h0+8*i, s[2*i+0]); + store64(h1+8*i, s[2*i+1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) +{ + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen/SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; + out1 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; + + if(outlen%SHAKE128_RATE) + { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for(i=0;i + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/shake-a64/fors.c b/shake-a64/fors.c new file mode 100644 index 0000000..a19fc7e --- /dev/null +++ b/shake-a64/fors.c @@ -0,0 +1,198 @@ +#include +#include +#include + +#include "thash.h" +#include "fors.h" +#include "utils.h" +#include "utilsx2.h" +#include "hash.h" +#include "hashx2.h" +#include "thashx2.h" +#include "address.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) +{ + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2*8]) +{ + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) +{ + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2*8]) +{ + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2*8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) +{ + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j*8, addr_idx + j); + set_type(fors_leaf_addrx2 + j*8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0*SPX_N, + leaf + 1*SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j*8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0*SPX_N, + leaf + 1*SPX_N, + leaf + 0*SPX_N, + leaf + 1*SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) +{ + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= ((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) +{ + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2*8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i=0; i<2; i++) { + copy_keypair_addr(fors_tree_addr + 8*i, fors_addr); + set_type(fors_tree_addr + 8*i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8*i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i*SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) +{ + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i*SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/shake-a64/fors.h b/shake-a64/fors.h new file mode 120000 index 0000000..07156bd --- /dev/null +++ b/shake-a64/fors.h @@ -0,0 +1 @@ +../ref/fors.h \ No newline at end of file diff --git a/shake-a64/hash.h b/shake-a64/hash.h new file mode 120000 index 0000000..cffc52b --- /dev/null +++ b/shake-a64/hash.h @@ -0,0 +1 @@ +../ref/hash.h \ No newline at end of file diff --git a/shake-a64/hash_shake.c b/shake-a64/hash_shake.c new file mode 120000 index 0000000..1d9d0cd --- /dev/null +++ b/shake-a64/hash_shake.c @@ -0,0 +1 @@ +../ref/hash_shake.c \ No newline at end of file diff --git a/shake-a64/hash_shakex2.c b/shake-a64/hash_shakex2.c new file mode 100644 index 0000000..d6f36c2 --- /dev/null +++ b/shake-a64/hash_shakex2.c @@ -0,0 +1,51 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "fips202x2.h" +#include "f1600x2.h" +#include "hashx2.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2*8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N/8; i++) { + uint64_t x = load64(ctx->pub_seed + 8*i); + state[2*i] = x; + state[2*i+1] = x; + } + for (int i = 0; i < 4; i++) { + state[2*(SPX_N/8 + i)] = (((uint64_t)addrx2[1+2*i]) << 32) + | (uint64_t)addrx2[2*i]; + state[2*(SPX_N/8 + i) + 1] = (((uint64_t)addrx2[8+1+2*i]) << 32) + | (uint64_t)addrx2[8+2*i]; + } + for (int i = 0; i < SPX_N/8; i++) { + uint64_t x = load64(ctx->sk_seed + 8*i); + state[2*(SPX_N/8+i+4)] = x; + state[2*(SPX_N/8+i+4)+1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2*(SPX_N/4+4)] = 0x1f; + state[2*(SPX_N/4+4)+1] = 0x1f; + + state[2*16] = 0x80ULL << 56; + state[2*16+1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N/8; i++) { + store64(out0 + 8*i, state[2*i]); + store64(out1 + 8*i, state[2*i+1]); + } +} diff --git a/shake-a64/hashx2.h b/shake-a64/hashx2.h new file mode 100644 index 0000000..25ce94d --- /dev/null +++ b/shake-a64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include +#include "context.h" +#include "params.h" + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2*8]); + +#endif diff --git a/shake-a64/merkle.c b/shake-a64/merkle.c new file mode 100644 index 0000000..b2791d1 --- /dev/null +++ b/shake-a64/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" +#include "merkle.h" +#include "address.h" +#include "params.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx* ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) +{ + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2*8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j=0; j<2; j++) { + set_type(&tree_addrx2[8*j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8*j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8*j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8*j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8*j], wots_addr); + copy_subtree_addr(&info.pk_addr[8*j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) +{ + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/shake-a64/merkle.h b/shake-a64/merkle.h new file mode 120000 index 0000000..7d167ed --- /dev/null +++ b/shake-a64/merkle.h @@ -0,0 +1 @@ +../ref/merkle.h \ No newline at end of file diff --git a/shake-a64/params.h b/shake-a64/params.h new file mode 120000 index 0000000..53133cc --- /dev/null +++ b/shake-a64/params.h @@ -0,0 +1 @@ +../ref/params.h \ No newline at end of file diff --git a/shake-a64/params/params-sphincs-shake-128f.h b/shake-a64/params/params-sphincs-shake-128f.h new file mode 120000 index 0000000..c65db98 --- /dev/null +++ b/shake-a64/params/params-sphincs-shake-128f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-128f.h \ No newline at end of file diff --git a/shake-a64/params/params-sphincs-shake-128s.h b/shake-a64/params/params-sphincs-shake-128s.h new file mode 120000 index 0000000..18671f7 --- /dev/null +++ b/shake-a64/params/params-sphincs-shake-128s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-128s.h \ No newline at end of file diff --git a/shake-a64/params/params-sphincs-shake-192f.h b/shake-a64/params/params-sphincs-shake-192f.h new file mode 120000 index 0000000..d071e35 --- /dev/null +++ b/shake-a64/params/params-sphincs-shake-192f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-192f.h \ No newline at end of file diff --git a/shake-a64/params/params-sphincs-shake-192s.h b/shake-a64/params/params-sphincs-shake-192s.h new file mode 120000 index 0000000..267e2c8 --- /dev/null +++ b/shake-a64/params/params-sphincs-shake-192s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-192s.h \ No newline at end of file diff --git a/shake-a64/params/params-sphincs-shake-256f.h b/shake-a64/params/params-sphincs-shake-256f.h new file mode 120000 index 0000000..3b4743b --- /dev/null +++ b/shake-a64/params/params-sphincs-shake-256f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-256f.h \ No newline at end of file diff --git a/shake-a64/params/params-sphincs-shake-256s.h b/shake-a64/params/params-sphincs-shake-256s.h new file mode 120000 index 0000000..0795ee1 --- /dev/null +++ b/shake-a64/params/params-sphincs-shake-256s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-256s.h \ No newline at end of file diff --git a/shake-a64/randombytes.c b/shake-a64/randombytes.c new file mode 120000 index 0000000..59a42a5 --- /dev/null +++ b/shake-a64/randombytes.c @@ -0,0 +1 @@ +../ref/randombytes.c \ No newline at end of file diff --git a/shake-a64/randombytes.h b/shake-a64/randombytes.h new file mode 120000 index 0000000..055e443 --- /dev/null +++ b/shake-a64/randombytes.h @@ -0,0 +1 @@ +../ref/randombytes.h \ No newline at end of file diff --git a/shake-a64/rng.c b/shake-a64/rng.c new file mode 120000 index 0000000..6e2fdac --- /dev/null +++ b/shake-a64/rng.c @@ -0,0 +1 @@ +../ref/rng.c \ No newline at end of file diff --git a/shake-a64/rng.h b/shake-a64/rng.h new file mode 120000 index 0000000..d678c7c --- /dev/null +++ b/shake-a64/rng.h @@ -0,0 +1 @@ +../ref/rng.h \ No newline at end of file diff --git a/shake-a64/shake_offsets.h b/shake-a64/shake_offsets.h new file mode 120000 index 0000000..8cfe4c0 --- /dev/null +++ b/shake-a64/shake_offsets.h @@ -0,0 +1 @@ +../ref/shake_offsets.h \ No newline at end of file diff --git a/shake-a64/sign.c b/shake-a64/sign.c new file mode 120000 index 0000000..42fea88 --- /dev/null +++ b/shake-a64/sign.c @@ -0,0 +1 @@ +../ref/sign.c \ No newline at end of file diff --git a/shake-a64/test/benchmark.c b/shake-a64/test/benchmark.c new file mode 100644 index 0000000..a1affb0 --- /dev/null +++ b/shake-a64/test/benchmark.c @@ -0,0 +1,175 @@ +#define _POSIX_C_SOURCE 199309L + +#include +#include +#include + +#include "../thash.h" +#include "../thashx2.h" +#include "../api.h" +#include "../f1600x2.h" +#include "../fors.h" +#include "../wots.h" +#include "../wotsx2.h" +#include "../params.h" +#include "../randombytes.h" + +#include "cycles.h" + +#define SPX_MLEN 32 +#define NTESTS 10 + +static void wots_gen_pkx2(unsigned char *pk, const spx_ctx *ctx, + uint32_t addr[8]); + +static int cmp_llu(const void *a, const void*b) +{ + if(*(unsigned long long *)a < *(unsigned long long *)b) return -1; + if(*(unsigned long long *)a > *(unsigned long long *)b) return 1; + return 0; +} + +static unsigned long long median(unsigned long long *l, size_t llen) +{ + qsort(l,llen,sizeof(unsigned long long),cmp_llu); + + if(llen%2) return l[llen/2]; + else return (l[llen/2-1]+l[llen/2])/2; +} + +static void delta(unsigned long long *l, size_t llen) +{ + unsigned int i; + for(i = 0; i < llen - 1; i++) { + l[i] = l[i+1] - l[i]; + } +} + +static void printfcomma (unsigned long long n) +{ + if (n < 1000) { + printf("%llu", n); + return; + } + printfcomma(n / 1000); + printf (",%03llu", n % 1000); +} + +static void printfalignedcomma (unsigned long long n, int len) +{ + unsigned long long ncopy = n; + int i = 0; + + while (ncopy > 9) { + len -= 1; + ncopy /= 10; + i += 1; // to account for commas + } + i = i/3 - 1; // to account for commas + for (; i < len; i++) { + printf(" "); + } + printfcomma(n); +} + +static void display_result(double result, unsigned long long *l, size_t llen, unsigned long long mul) +{ + unsigned long long med; + + result /= NTESTS; + delta(l, NTESTS + 1); + med = median(l, llen); + printf("avg. %11.2lf us (%2.2lf sec); median ", result, result / 1e6); + printfalignedcomma(med, 12); + printf(" cycles, %5llux: ", mul); + printfalignedcomma(mul*med, 12); + printf(" cycles\n"); +} + +#define MEASURE_GENERIC(TEXT, MUL, FNCALL, CORR)\ + printf(TEXT);\ + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);\ + for(i = 0; i < NTESTS; i++) {\ + t[i] = cpucycles() / CORR;\ + FNCALL;\ + }\ + t[NTESTS] = cpucycles();\ + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop);\ + result = ((stop.tv_sec - start.tv_sec) * 1e6 + \ + (stop.tv_nsec - start.tv_nsec) / 1e3) / (double)CORR;\ + display_result(result, t, NTESTS, MUL); +#define MEASURT(TEXT, MUL, FNCALL)\ + MEASURE_GENERIC(\ + TEXT, MUL,\ + do {\ + for (int j = 0; j < 1000; j++) {\ + FNCALL;\ + }\ + } while (0);,\ + 1000); +#define MEASURE(TEXT, MUL, FNCALL) MEASURE_GENERIC(TEXT, MUL, FNCALL, 1) + +int main(void) +{ + init_cpucycles(); + /* Make stdout buffer more responsive. */ + setbuf(stdout, NULL); + + spx_ctx ctx; + unsigned char pk[SPX_PK_BYTES]; + unsigned char sk[SPX_SK_BYTES]; + unsigned char *m = malloc(SPX_MLEN); + unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); + unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); + + unsigned char fors_pk[SPX_FORS_PK_BYTES]; + unsigned char fors_m[SPX_FORS_MSG_BYTES]; + unsigned char fors_sig[SPX_FORS_BYTES]; + unsigned char addr[SPX_ADDR_BYTES*2]; + unsigned char wots_pk[4*SPX_WOTS_PK_BYTES]; + unsigned char block[SPX_N]; + + unsigned long long smlen; + unsigned long long mlen; + unsigned long long t[NTESTS+1]; + struct timespec start, stop; + double result; + int i; + uint64_t statex2[50]; + + randombytes(m, SPX_MLEN); + randombytes(addr, SPX_ADDR_BYTES*2); + + printf("Parameters: n = %d, h = %d, d = %d, b = %d, k = %d, w = %d\n", + SPX_N, SPX_FULL_HEIGHT, SPX_D, SPX_FORS_HEIGHT, SPX_FORS_TREES, + SPX_WOTS_W); + + printf("Running %d iterations.\n", NTESTS); + + MEASURT("thash ", 1, thash(block, block, 1, &ctx, (uint32_t*)addr)); + MEASURT("f1600x2 ", 1, f1600x2(statex2)); + MEASURT("thashx2 ", 1, thashx2(block, block, block, block, 1, &ctx, (uint32_t*)addr)); + MEASURE("Generating keypair.. ", 1, crypto_sign_keypair(pk, sk)); + MEASURE(" - WOTS pk gen 2x.. ", (1 << SPX_TREE_HEIGHT) / 2, wots_gen_pkx2(wots_pk, &ctx, (uint32_t *) addr)); + MEASURE("Signing.. ", 1, crypto_sign(sm, &smlen, m, SPX_MLEN, sk)); + MEASURE(" - FORS signing.. ", 1, fors_sign(fors_sig, fors_pk, fors_m, &ctx, (uint32_t *) addr)); + MEASURE(" - WOTS pk gen x2.. ", SPX_D * (1 << SPX_TREE_HEIGHT) / 2, wots_gen_pkx2(wots_pk, &ctx, (uint32_t *) addr)); + MEASURE("Verifying.. ", 1, crypto_sign_open(mout, &mlen, sm, smlen, pk)); + + printf("Signature size: %d (%.2f KiB)\n", SPX_BYTES, SPX_BYTES / 1024.0); + printf("Public key size: %d (%.2f KiB)\n", SPX_PK_BYTES, SPX_PK_BYTES / 1024.0); + printf("Secret key size: %d (%.2f KiB)\n", SPX_SK_BYTES, SPX_SK_BYTES / 1024.0); + + free(m); + free(sm); + free(mout); + + return 0; +} + +static void wots_gen_pkx2(unsigned char *pk, const spx_ctx *ctx, uint32_t addr[8]) { + struct leaf_info_x2 leaf; + unsigned steps[ SPX_WOTS_LEN ] = { 0 }; + INITIALIZE_LEAF_INFO_X2(leaf, addr, steps); + wots_gen_leafx2(pk, ctx, 0, &leaf); +} diff --git a/shake-a64/test/cycles.c b/shake-a64/test/cycles.c new file mode 120000 index 0000000..513f008 --- /dev/null +++ b/shake-a64/test/cycles.c @@ -0,0 +1 @@ +../../ref/test/cycles.c \ No newline at end of file diff --git a/shake-a64/test/cycles.h b/shake-a64/test/cycles.h new file mode 120000 index 0000000..c386581 --- /dev/null +++ b/shake-a64/test/cycles.h @@ -0,0 +1 @@ +../../ref/test/cycles.h \ No newline at end of file diff --git a/shake-a64/test/fors.c b/shake-a64/test/fors.c new file mode 120000 index 0000000..b2bccee --- /dev/null +++ b/shake-a64/test/fors.c @@ -0,0 +1 @@ +../../ref/test/fors.c \ No newline at end of file diff --git a/shake-a64/test/spx.c b/shake-a64/test/spx.c new file mode 120000 index 0000000..7af26df --- /dev/null +++ b/shake-a64/test/spx.c @@ -0,0 +1 @@ +../../ref/test/spx.c \ No newline at end of file diff --git a/shake-a64/test/thashx2.c b/shake-a64/test/thashx2.c new file mode 100644 index 0000000..0b55b13 --- /dev/null +++ b/shake-a64/test/thashx2.c @@ -0,0 +1,43 @@ +#include +#include + +#include "../thashx2.h" +#include "../thash.h" +#include "../randombytes.h" +#include "../params.h" + +int main(void) +{ + /* Make stdout buffer more responsive. */ + setbuf(stdout, NULL); + + unsigned char input[2*SPX_N]; + unsigned char output[2*SPX_N]; + unsigned char out2[2*SPX_N]; + uint32_t addr[2*8] = {0}; + unsigned int j; + spx_ctx ctx; + + randombytes(ctx.pub_seed, SPX_N); + randombytes(input, 4*SPX_N); + randombytes((unsigned char *)addr, 2 * 8 * sizeof(uint32_t)); + + printf("Testing if thash matches thashx2.. "); + + for (j = 0; j < 2; j++) { + thash(out2 + j * SPX_N, input + j * SPX_N, 1, &ctx, addr + j*8); + } + + thashx2(output + 0*SPX_N, + output + 1*SPX_N, + input + 0*SPX_N, + input + 1*SPX_N, + 1, &ctx, addr); + + if (memcmp(out2, output, 2 * SPX_N)) { + printf("failed!\n"); + return -1; + } + printf("successful.\n"); + return 0; +} diff --git a/shake-a64/thash.h b/shake-a64/thash.h new file mode 100644 index 0000000..ec9222c --- /dev/null +++ b/shake-a64/thash.h @@ -0,0 +1,12 @@ +#ifndef SPX_THASHX2_AS_ONE +#define SPX_THASHX2_AS_ONE + +#include +#include "context.h" + +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + + +#endif + diff --git a/shake-a64/thash_shake_robustx2.c b/shake-a64/thash_shake_robustx2.c new file mode 100644 index 0000000..77e09ff --- /dev/null +++ b/shake-a64/thash_shake_robustx2.c @@ -0,0 +1,112 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2*8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2*8]) +{ + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + uint64_t state2[50]; + + for (int i = 0; i < SPX_N/8; i++) { + uint64_t x = load64(ctx->pub_seed + 8*i); + state[2*i] = x; + state[2*i+1] = x; + } + for (int i = 0; i < 4; i++) { + state[2*(SPX_N/8 + i)] = (((uint64_t)addrx2[1+2*i]) << 32) + | (uint64_t)addrx2[2*i]; + state[2*(SPX_N/8 + i) + 1] = (((uint64_t)addrx2[8+1+2*i]) << 32) + | (uint64_t)addrx2[8+2*i]; + } + + /* Domain separator and padding. */ + state[2*16] = 0x80ULL << 56; + state[2*16+1] = 0x80ULL << 56; + + state[2*((SPX_N/8)+4)] ^= 0x1f; + state[2*((SPX_N/8)+4)+1] ^= 0x1f; + + /* We will permutate state2 with f1600x2 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is almost identical. */ + memcpy(state2, state, 400); + + f1600x2(state); + + /* By copying from state, state2 already contains the pub_seed + * and address. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N/8) * inblocks; i++) { + state2[2*(SPX_N/8+4+i)] = state[2*i] ^ load64(in0 + 8*i); + state2[2*(SPX_N/8+4+i)+1] = state[2*i+1] ^ load64(in1 + 8*i); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[2*((SPX_N/8)*(1+inblocks)+4)] ^= 0x1f; + state2[2*((SPX_N/8)*(1+inblocks)+4)+1] ^= 0x1f; + + f1600x2(state2); + + for (int i = 0; i < SPX_N/8; i++) { + store64(out0 + 8*i, state2[2*i]); + store64(out1 + 8*i, state2[2*i+1]); + } + } else { + SPX_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + SPX_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + SPX_VLA(unsigned char, bitmask0, inblocks * SPX_N); + SPX_VLA(unsigned char, bitmask1, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0*8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1*8, SPX_ADDR_BYTES); + + shake256x2(bitmask0, bitmask1, inblocks * SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + } + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + } +} diff --git a/shake-a64/thash_shake_simplex2.c b/shake-a64/thash_shake_simplex2.c new file mode 100644 index 0000000..0bd7130 --- /dev/null +++ b/shake-a64/thash_shake_simplex2.c @@ -0,0 +1,83 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2*8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2*8]) +{ + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + for (int i = 0; i < SPX_N/8; i++) { + uint64_t x = load64(ctx->pub_seed + 8*i); + state[2*i] = x; + state[2*i+1] = x; + } + for (int i = 0; i < 4; i++) { + state[2*(SPX_N/8 + i)] = (((uint64_t)addrx2[1+2*i]) << 32) + | (uint64_t)addrx2[2*i]; + state[2*(SPX_N/8 + i) + 1] = (((uint64_t)addrx2[8+1+2*i]) << 32) + | (uint64_t)addrx2[8+2*i]; + } + + for (unsigned int i = 0; i < (SPX_N/8) * inblocks; i++) { + state[2*(SPX_N/8+4+i)] = load64(in0+8*i); + state[2*(SPX_N/8+4+i)+1] = load64(in1+8*i); + } + + /* Domain separator and padding. */ + state[2*16] = 0x80ULL << 56; + state[2*16+1] = 0x80ULL << 56; + + state[2*((SPX_N/8)*(1+inblocks)+4)] ^= 0x1f; + state[2*((SPX_N/8)*(1+inblocks)+4)+1] ^= 0x1f; + + f1600x2(state); + + for (int i = 0; i < SPX_N/8; i++) { + store64(out0 + 8*i, state[2*i]); + store64(out1 + 8*i, state[2*i+1]); + } + } else { + SPX_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + SPX_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0*8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1*8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + } +} diff --git a/shake-a64/thashx2.h b/shake-a64/thashx2.h new file mode 100644 index 0000000..bde4f59 --- /dev/null +++ b/shake-a64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include +#include "context.h" +#include "params.h" + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2*8]); + +#endif diff --git a/shake-a64/utils.c b/shake-a64/utils.c new file mode 120000 index 0000000..e8ef6eb --- /dev/null +++ b/shake-a64/utils.c @@ -0,0 +1 @@ +../ref/utils.c \ No newline at end of file diff --git a/shake-a64/utils.h b/shake-a64/utils.h new file mode 120000 index 0000000..51b0d39 --- /dev/null +++ b/shake-a64/utils.h @@ -0,0 +1 @@ +../ref/utils.h \ No newline at end of file diff --git a/shake-a64/utilsx2.c b/shake-a64/utilsx2.c new file mode 100644 index 0000000..7b75fb4 --- /dev/null +++ b/shake-a64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utils.h" +#include "utilsx2.h" +#include "params.h" +#include "thashx2.h" +#include "address.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char* /* Where to write the leaves */, + const spx_ctx*, + uint32_t idx, void *info), + uint32_t tree_addrx2[2*8], + void *info) +{ + /* This is where we keep the intermediate nodes */ + SPX_VLA(unsigned char, stackx2, 2 * tree_height * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height-1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2*SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2*idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h=0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1*SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1*SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf&1)^1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j*8, h + 1); + set_tree_index(tree_addrx2 + j*8, + (2/2) * (internal_idx&~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/shake-a64/utilsx2.h b/shake-a64/utilsx2.h new file mode 100644 index 0000000..3fcfb9d --- /dev/null +++ b/shake-a64/utilsx2.h @@ -0,0 +1,28 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char* /* Where to write the leaves */, + const spx_ctx* /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2*8], void *info); + +#endif diff --git a/shake-a64/wots.c b/shake-a64/wots.c new file mode 100644 index 0000000..ef0235b --- /dev/null +++ b/shake-a64/wots.c @@ -0,0 +1,261 @@ +#include +#include + +#include "utils.h" +#include "utilsx2.h" +#include "hash.h" +#include "hashx2.h" +#include "thashx2.h" +#include "wots.h" +#include "wotsx2.h" +#include "address.h" +#include "params.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) +{ + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8*2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs+j*8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN*SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i+j < SPX_WOTS_LEN; j++) { + idx = idxs[i+j]; + set_chain_addr(addrs+j*8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i+watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs+j*8, k + start[idxs[i+j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) +{ + int in = 0; + int out = 0; + unsigned char total; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) +{ + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) +{ + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) +{ + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j*8, leaf_idx + j ); + set_keypair_addr( pk_addr + j*8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j*8, i); + set_hash_addr(leaf_addr + j*8, 0); + set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0*wots_offset, + buffer + 1*wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k=0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index*wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) break; + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j*8, k); + } + thashx2(buffer + 0*wots_offset, + buffer + 1*wots_offset, + buffer + 0*wots_offset, + buffer + 1*wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0*SPX_N, + dest + 1*SPX_N, + pk_buffer + 0*wots_offset, + pk_buffer + 1*wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/shake-a64/wots.h b/shake-a64/wots.h new file mode 120000 index 0000000..8c327ea --- /dev/null +++ b/shake-a64/wots.h @@ -0,0 +1 @@ +../ref/wots.h \ No newline at end of file diff --git a/shake-a64/wotsx2.h b/shake-a64/wotsx2.h new file mode 100644 index 0000000..6237737 --- /dev/null +++ b/shake-a64/wotsx2.h @@ -0,0 +1,40 @@ +#if !defined( WOTSX2_H_ ) +#define WOTSX2_H_ + +#include +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2*8]; + uint32_t pk_addr[2*8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + info.wots_sig = 0; \ + info.wots_sign_leaf = ~0; \ + info.wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &info.leaf_addr[8*i], addr, 32 ); \ + memcpy( &info.pk_addr[8*i], addr, 32 ); \ + } \ +} + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/shake-avx2/.gitignore b/shake-avx2/.gitignore new file mode 100644 index 0000000..20d83ac --- /dev/null +++ b/shake-avx2/.gitignore @@ -0,0 +1,6 @@ +test/* +!test/*.c +PQCsignKAT_*.rsp +PQCsignKAT_*.req +PQCgenKAT_sign +keccak4x/KeccakP-1600-times4-SIMD256.o \ No newline at end of file diff --git a/shake-avx2/Makefile b/shake-avx2/Makefile new file mode 100644 index 0000000..fa8421c --- /dev/null +++ b/shake-avx2/Makefile @@ -0,0 +1,56 @@ +PARAMS = sphincs-shake-128f +THASH = robust + +CC = /usr/bin/gcc +CFLAGS = -Wall -Wextra -Wpedantic -Wmissing-prototypes -O3 -std=c99 -march=native -fomit-frame-pointer -flto -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) + +SOURCES = hash_shake.c hash_shakex4.c thash_shake_$(THASH).c thash_shake_$(THASH)x4.c address.c randombytes.c merkle.c wots.c utils.c utilsx4.c fors.c sign.c fips202.c fips202x4.c keccak4x/KeccakP-1600-times4-SIMD256.o +HEADERS = params.h hash.h hashx4.h thash.h thashx4.h address.h randombytes.h merkle.h wots.h utils.h utilsx4.h fors.h api.h fips202.h fips202x4.h + +DET_SOURCES = $(SOURCES:randombytes.%=rng.%) +DET_HEADERS = $(HEADERS:randombytes.%=rng.%) + +TESTS = test/fors \ + test/spx \ + test/thashx4 \ + +BENCHMARK = test/benchmark + +.PHONY: clean test benchmark + +default: PQCgenKAT_sign + +all: PQCgenKAT_sign tests benchmarks + +tests: $(TESTS) + +test: $(TESTS:=.exec) + +benchmarks: $(BENCHMARK) + +benchmark: $(BENCHMARK:=.exec) + +PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) + $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto + +test/%: test/%.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) + +test/%.exec: test/% + @$< + +keccak4x/KeccakP-1600-times4-SIMD256.o: keccak4x/align.h \ + keccak4x/brg_endian.h \ + keccak4x/KeccakP-1600-times4-SIMD256.c \ + keccak4x/KeccakP-1600-times4-SnP.h \ + keccak4x/KeccakP-1600-unrolling.macros \ + keccak4x/SIMD256-config.h + $(CC) $(CFLAGS) -c keccak4x/KeccakP-1600-times4-SIMD256.c -o $@ + +clean: + -$(RM) keccak4x/KeccakP-1600-times4-SIMD256.o + -$(RM) $(TESTS) + -$(RM) $(BENCHMARK) + -$(RM) PQCgenKAT_sign + -$(RM) PQCsignKAT_*.rsp + -$(RM) PQCsignKAT_*.req diff --git a/shake-avx2/PQCgenKAT_sign.c b/shake-avx2/PQCgenKAT_sign.c new file mode 120000 index 0000000..a17dbe2 --- /dev/null +++ b/shake-avx2/PQCgenKAT_sign.c @@ -0,0 +1 @@ +../ref/PQCgenKAT_sign.c \ No newline at end of file diff --git a/shake-avx2/address.c b/shake-avx2/address.c new file mode 120000 index 0000000..02c52c6 --- /dev/null +++ b/shake-avx2/address.c @@ -0,0 +1 @@ +../ref/address.c \ No newline at end of file diff --git a/shake-avx2/address.h b/shake-avx2/address.h new file mode 120000 index 0000000..e670da5 --- /dev/null +++ b/shake-avx2/address.h @@ -0,0 +1 @@ +../ref/address.h \ No newline at end of file diff --git a/shake-avx2/api.h b/shake-avx2/api.h new file mode 120000 index 0000000..ea89e0a --- /dev/null +++ b/shake-avx2/api.h @@ -0,0 +1 @@ +../ref/api.h \ No newline at end of file diff --git a/shake-avx2/context.h b/shake-avx2/context.h new file mode 100644 index 0000000..993c9ce --- /dev/null +++ b/shake-avx2/context.h @@ -0,0 +1,13 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#endif diff --git a/shake-avx2/fips202.c b/shake-avx2/fips202.c new file mode 120000 index 0000000..da2fa42 --- /dev/null +++ b/shake-avx2/fips202.c @@ -0,0 +1 @@ +../ref/fips202.c \ No newline at end of file diff --git a/shake-avx2/fips202.h b/shake-avx2/fips202.h new file mode 120000 index 0000000..c759415 --- /dev/null +++ b/shake-avx2/fips202.h @@ -0,0 +1 @@ +../ref/fips202.h \ No newline at end of file diff --git a/shake-avx2/fips202x4.c b/shake-avx2/fips202x4.c new file mode 100644 index 0000000..b875467 --- /dev/null +++ b/shake-avx2/fips202x4.c @@ -0,0 +1,225 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) ((a << offset) ^ (a >> (64-offset))) + +static uint64_t load64(const unsigned char *x) +{ + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) +{ + unsigned int i; + + for(i=0; i<8; ++i) { + x[i] = u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) +{ + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) + { + for (i = 0; i < r / 8; ++i) + { + ss[4*i+0] ^= load64(m0 + 8 * i); + ss[4*i+1] ^= load64(m1 + 8 * i); + ss[4*i+2] ^= load64(m2 + 8 * i); + ss[4*i+3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) + { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) + { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) + { + ss[4*i+0] ^= load64(t0 + 8 * i); + ss[4*i+1] ^= load64(t1 + 8 * i); + ss[4*i+2] ^= load64(t2 + 8 * i); + ss[4*i+3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) +{ + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while(nblocks > 0) + { + KeccakF1600_StatePermute4x(s); + for(i=0;i<(r>>3);i++) + { + store64(h0+8*i, ss[4*i+0]); + store64(h1+8*i, ss[4*i+1]); + store64(h2+8*i, ss[4*i+2]); + store64(h3+8*i, ss[4*i+3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) +{ + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for(i=0;i<25;i++) + s[i] = _mm256_xor_si256(s[i], s[i]); + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen/SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; + out1 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; + out2 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; + out3 += (outlen/SHAKE128_RATE)*SHAKE128_RATE; + + if(outlen%SHAKE128_RATE) + { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for(i=0;i + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/shake-avx2/fors.c b/shake-avx2/fors.c new file mode 100644 index 0000000..8b634f4 --- /dev/null +++ b/shake-avx2/fors.c @@ -0,0 +1,209 @@ +#include +#include +#include + +#include "fors.h" +#include "utils.h" +#include "utilsx4.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "address.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) +{ + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4*8]) +{ + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) +{ + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4*8]) +{ + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4*8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) +{ + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j*8, addr_idx + j); + set_type(fors_leaf_addrx4 + j*8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0*SPX_N, + leaf + 1*SPX_N, + leaf + 2*SPX_N, + leaf + 3*SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j*8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0*SPX_N, + leaf + 1*SPX_N, + leaf + 2*SPX_N, + leaf + 3*SPX_N, + leaf + 0*SPX_N, + leaf + 1*SPX_N, + leaf + 2*SPX_N, + leaf + 3*SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) +{ + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= ((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) +{ + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4*8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i=0; i<4; i++) { + copy_keypair_addr(fors_tree_addr + 8*i, fors_addr); + set_type(fors_tree_addr + 8*i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8*i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i*SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) +{ + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i*SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/shake-avx2/fors.h b/shake-avx2/fors.h new file mode 120000 index 0000000..07156bd --- /dev/null +++ b/shake-avx2/fors.h @@ -0,0 +1 @@ +../ref/fors.h \ No newline at end of file diff --git a/shake-avx2/hash.h b/shake-avx2/hash.h new file mode 120000 index 0000000..cffc52b --- /dev/null +++ b/shake-avx2/hash.h @@ -0,0 +1 @@ +../ref/hash.h \ No newline at end of file diff --git a/shake-avx2/hash_shake.c b/shake-avx2/hash_shake.c new file mode 120000 index 0000000..1d9d0cd --- /dev/null +++ b/shake-avx2/hash_shake.c @@ -0,0 +1 @@ +../ref/hash_shake.c \ No newline at end of file diff --git a/shake-avx2/hash_shakex4.c b/shake-avx2/hash_shakex4.c new file mode 100644 index 0000000..93ee3cc --- /dev/null +++ b/shake-avx2/hash_shakex4.c @@ -0,0 +1,63 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "fips202x4.h" +#include "hashx4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4*8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N/8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t*)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N/8+i] = _mm256_set_epi32( + addrx4[3*8+1+2*i], + addrx4[3*8+2*i], + addrx4[2*8+1+2*i], + addrx4[2*8+2*i], + addrx4[8+1+2*i], + addrx4[8+2*i], + addrx4[1+2*i], + addrx4[2*i] + ); + } + for (int i = 0; i < SPX_N/8; i++) { + state[SPX_N/8+i+4] = _mm256_set1_epi64x(((int64_t*)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N/4+4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N/4+5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N/8; i++) { + ((int64_t*)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t*)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t*)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t*)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/shake-avx2/hashx4.h b/shake-avx2/hashx4.h new file mode 100644 index 0000000..1c19618 --- /dev/null +++ b/shake-avx2/hashx4.h @@ -0,0 +1,16 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4*8]); + +#endif diff --git a/shake-avx2/keccak4x/KeccakP-1600-times4-SIMD256.c b/shake-avx2/keccak4x/KeccakP-1600-times4-SIMD256.c new file mode 100644 index 0000000..7a0428f --- /dev/null +++ b/shake-avx2/keccak4x/KeccakP-1600-times4-SIMD256.c @@ -0,0 +1,1030 @@ +/* +Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, +Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby +denoted as "the implementer". + +For more information, feedback or questions, please refer to our websites: +http://keccak.noekeon.org/ +http://keyak.noekeon.org/ +http://ketje.noekeon.org/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "align.h" +#include "KeccakP-1600-times4-SnP.h" +#include "SIMD256-config.h" + +#include "brg_endian.h" +#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN) +#error Expecting a little-endian platform +#endif + +typedef unsigned char UINT8; +typedef unsigned long long int UINT64; +typedef __m128i V128; +typedef __m256i V256; + +#define laneIndex(instanceIndex, lanePosition) ((lanePosition)*4 + instanceIndex) + +#if defined(KeccakP1600times4_useAVX2) + #define ANDnu256(a, b) _mm256_andnot_si256(a, b) + #define CONST256(a) _mm256_load_si256((const V256 *)&(a)) + #define CONST256_64(a) (V256)_mm256_broadcast_sd((const double*)(&a)) + #define LOAD256(a) _mm256_load_si256((const V256 *)&(a)) + #define LOAD256u(a) _mm256_loadu_si256((const V256 *)&(a)) + #define LOAD4_64(a, b, c, d) _mm256_set_epi64x((UINT64)(a), (UINT64)(b), (UINT64)(c), (UINT64)(d)) + #define ROL64in256(d, a, o) d = _mm256_or_si256(_mm256_slli_epi64(a, o), _mm256_srli_epi64(a, 64-(o))) + #define ROL64in256_8(d, a) d = _mm256_shuffle_epi8(a, CONST256(rho8)) + #define ROL64in256_56(d, a) d = _mm256_shuffle_epi8(a, CONST256(rho56)) +static const UINT64 rho8[4] = {0x0605040302010007, 0x0E0D0C0B0A09080F, 0x1615141312111017, 0x1E1D1C1B1A19181F}; +static const UINT64 rho56[4] = {0x0007060504030201, 0x080F0E0D0C0B0A09, 0x1017161514131211, 0x181F1E1D1C1B1A19}; + #define STORE256(a, b) _mm256_store_si256((V256 *)&(a), b) + #define STORE256u(a, b) _mm256_storeu_si256((V256 *)&(a), b) + #define STORE2_128(ah, al, v) _mm256_storeu2_m128d((V128*)&(ah), (V128*)&(al), v) + #define XOR256(a, b) _mm256_xor_si256(a, b) + #define XOReq256(a, b) a = _mm256_xor_si256(a, b) + #define UNPACKL( a, b ) _mm256_unpacklo_epi64((a), (b)) + #define UNPACKH( a, b ) _mm256_unpackhi_epi64((a), (b)) + #define PERM128( a, b, c ) (V256)_mm256_permute2f128_ps((__m256)(a), (__m256)(b), c) + #define SHUFFLE64( a, b, c ) (V256)_mm256_shuffle_pd((__m256d)(a), (__m256d)(b), c) + + #define UNINTLEAVE() lanesL01 = UNPACKL( lanes0, lanes1 ), \ + lanesH01 = UNPACKH( lanes0, lanes1 ), \ + lanesL23 = UNPACKL( lanes2, lanes3 ), \ + lanesH23 = UNPACKH( lanes2, lanes3 ), \ + lanes0 = PERM128( lanesL01, lanesL23, 0x20 ), \ + lanes2 = PERM128( lanesL01, lanesL23, 0x31 ), \ + lanes1 = PERM128( lanesH01, lanesH23, 0x20 ), \ + lanes3 = PERM128( lanesH01, lanesH23, 0x31 ) + + #define INTLEAVE() lanesL01 = PERM128( lanes0, lanes2, 0x20 ), \ + lanesH01 = PERM128( lanes1, lanes3, 0x20 ), \ + lanesL23 = PERM128( lanes0, lanes2, 0x31 ), \ + lanesH23 = PERM128( lanes1, lanes3, 0x31 ), \ + lanes0 = SHUFFLE64( lanesL01, lanesH01, 0x00 ), \ + lanes1 = SHUFFLE64( lanesL01, lanesH01, 0x0F ), \ + lanes2 = SHUFFLE64( lanesL23, lanesH23, 0x00 ), \ + lanes3 = SHUFFLE64( lanesL23, lanesH23, 0x0F ) + +#endif + +#define SnP_laneLengthInBytes 8 + +void KeccakP1600times4_InitializeAll(void *states) +{ + memset(states, 0, KeccakP1600times4_statesSizeInBytes); +} + +void KeccakP1600times4_AddBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length) +{ + unsigned int sizeLeft = length; + unsigned int lanePosition = offset/SnP_laneLengthInBytes; + unsigned int offsetInLane = offset%SnP_laneLengthInBytes; + const unsigned char *curData = data; + UINT64 *statesAsLanes = (UINT64 *)states; + + if ((sizeLeft > 0) && (offsetInLane != 0)) { + unsigned int bytesInLane = SnP_laneLengthInBytes - offsetInLane; + UINT64 lane = 0; + if (bytesInLane > sizeLeft) + bytesInLane = sizeLeft; + memcpy((unsigned char*)&lane + offsetInLane, curData, bytesInLane); + statesAsLanes[laneIndex(instanceIndex, lanePosition)] ^= lane; + sizeLeft -= bytesInLane; + lanePosition++; + curData += bytesInLane; + } + + while(sizeLeft >= SnP_laneLengthInBytes) { + UINT64 lane = *((const UINT64*)curData); + statesAsLanes[laneIndex(instanceIndex, lanePosition)] ^= lane; + sizeLeft -= SnP_laneLengthInBytes; + lanePosition++; + curData += SnP_laneLengthInBytes; + } + + if (sizeLeft > 0) { + UINT64 lane = 0; + memcpy(&lane, curData, sizeLeft); + statesAsLanes[laneIndex(instanceIndex, lanePosition)] ^= lane; + } +} + +void KeccakP1600times4_AddLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset) +{ + V256 *stateAsLanes = (V256 *)states; + unsigned int i; + const UINT64 *curData0 = (const UINT64 *)data; + const UINT64 *curData1 = (const UINT64 *)(data+laneOffset*SnP_laneLengthInBytes); + const UINT64 *curData2 = (const UINT64 *)(data+laneOffset*2*SnP_laneLengthInBytes); + const UINT64 *curData3 = (const UINT64 *)(data+laneOffset*3*SnP_laneLengthInBytes); + V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; + + #define Xor_In( argIndex ) XOReq256(stateAsLanes[argIndex], LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) + + #define Xor_In4( argIndex ) lanes0 = LOAD256u( curData0[argIndex]),\ + lanes1 = LOAD256u( curData1[argIndex]),\ + lanes2 = LOAD256u( curData2[argIndex]),\ + lanes3 = LOAD256u( curData3[argIndex]),\ + INTLEAVE(),\ + XOReq256( stateAsLanes[argIndex+0], lanes0 ),\ + XOReq256( stateAsLanes[argIndex+1], lanes1 ),\ + XOReq256( stateAsLanes[argIndex+2], lanes2 ),\ + XOReq256( stateAsLanes[argIndex+3], lanes3 ) + + if ( laneCount >= 16 ) { + Xor_In4( 0 ); + Xor_In4( 4 ); + Xor_In4( 8 ); + Xor_In4( 12 ); + if ( laneCount >= 20 ) { + Xor_In4( 16 ); + for(i=20; i 0) && (offsetInLane != 0)) { + unsigned int bytesInLane = SnP_laneLengthInBytes - offsetInLane; + if (bytesInLane > sizeLeft) + bytesInLane = sizeLeft; + memcpy( ((unsigned char *)&statesAsLanes[laneIndex(instanceIndex, lanePosition)]) + offsetInLane, curData, bytesInLane); + sizeLeft -= bytesInLane; + lanePosition++; + curData += bytesInLane; + } + + while(sizeLeft >= SnP_laneLengthInBytes) { + UINT64 lane = *((const UINT64*)curData); + statesAsLanes[laneIndex(instanceIndex, lanePosition)] = lane; + sizeLeft -= SnP_laneLengthInBytes; + lanePosition++; + curData += SnP_laneLengthInBytes; + } + + if (sizeLeft > 0) { + memcpy(&statesAsLanes[laneIndex(instanceIndex, lanePosition)], curData, sizeLeft); + } +} + +void KeccakP1600times4_OverwriteLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset) +{ + V256 *stateAsLanes = (V256 *)states; + unsigned int i; + const UINT64 *curData0 = (const UINT64 *)data; + const UINT64 *curData1 = (const UINT64 *)(data+laneOffset*SnP_laneLengthInBytes); + const UINT64 *curData2 = (const UINT64 *)(data+laneOffset*2*SnP_laneLengthInBytes); + const UINT64 *curData3 = (const UINT64 *)(data+laneOffset*3*SnP_laneLengthInBytes); + V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; + + #define OverWr( argIndex ) STORE256(stateAsLanes[argIndex], LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) + + #define OverWr4( argIndex ) lanes0 = LOAD256u( curData0[argIndex]),\ + lanes1 = LOAD256u( curData1[argIndex]),\ + lanes2 = LOAD256u( curData2[argIndex]),\ + lanes3 = LOAD256u( curData3[argIndex]),\ + INTLEAVE(),\ + STORE256( stateAsLanes[argIndex+0], lanes0 ),\ + STORE256( stateAsLanes[argIndex+1], lanes1 ),\ + STORE256( stateAsLanes[argIndex+2], lanes2 ),\ + STORE256( stateAsLanes[argIndex+3], lanes3 ) + + if ( laneCount >= 16 ) { + OverWr4( 0 ); + OverWr4( 4 ); + OverWr4( 8 ); + OverWr4( 12 ); + if ( laneCount >= 20 ) { + OverWr4( 16 ); + for(i=20; i= SnP_laneLengthInBytes) { + statesAsLanes[laneIndex(instanceIndex, lanePosition)] = 0; + sizeLeft -= SnP_laneLengthInBytes; + lanePosition++; + } + + if (sizeLeft > 0) { + memset(&statesAsLanes[laneIndex(instanceIndex, lanePosition)], 0, sizeLeft); + } +} + +void KeccakP1600times4_ExtractBytes(const void *states, unsigned int instanceIndex, unsigned char *data, unsigned int offset, unsigned int length) +{ + unsigned int sizeLeft = length; + unsigned int lanePosition = offset/SnP_laneLengthInBytes; + unsigned int offsetInLane = offset%SnP_laneLengthInBytes; + unsigned char *curData = data; + const UINT64 *statesAsLanes = (const UINT64 *)states; + + if ((sizeLeft > 0) && (offsetInLane != 0)) { + unsigned int bytesInLane = SnP_laneLengthInBytes - offsetInLane; + if (bytesInLane > sizeLeft) + bytesInLane = sizeLeft; + memcpy( curData, ((unsigned char *)&statesAsLanes[laneIndex(instanceIndex, lanePosition)]) + offsetInLane, bytesInLane); + sizeLeft -= bytesInLane; + lanePosition++; + curData += bytesInLane; + } + + while(sizeLeft >= SnP_laneLengthInBytes) { + *(UINT64*)curData = statesAsLanes[laneIndex(instanceIndex, lanePosition)]; + sizeLeft -= SnP_laneLengthInBytes; + lanePosition++; + curData += SnP_laneLengthInBytes; + } + + if (sizeLeft > 0) { + memcpy( curData, &statesAsLanes[laneIndex(instanceIndex, lanePosition)], sizeLeft); + } +} + +void KeccakP1600times4_ExtractLanesAll(const void *states, unsigned char *data, unsigned int laneCount, unsigned int laneOffset) +{ + UINT64 *curData0 = (UINT64 *)data; + UINT64 *curData1 = (UINT64 *)(data+laneOffset*1*SnP_laneLengthInBytes); + UINT64 *curData2 = (UINT64 *)(data+laneOffset*2*SnP_laneLengthInBytes); + UINT64 *curData3 = (UINT64 *)(data+laneOffset*3*SnP_laneLengthInBytes); + + const V256 *stateAsLanes = (const V256 *)states; + const UINT64 *stateAsLanes64 = (const UINT64*)states; + V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; + unsigned int i; + + #define Extr( argIndex ) curData0[argIndex] = stateAsLanes64[4*(argIndex)], \ + curData1[argIndex] = stateAsLanes64[4*(argIndex)+1], \ + curData2[argIndex] = stateAsLanes64[4*(argIndex)+2], \ + curData3[argIndex] = stateAsLanes64[4*(argIndex)+3] + + #define Extr4( argIndex ) lanes0 = LOAD256( stateAsLanes[argIndex+0] ), \ + lanes1 = LOAD256( stateAsLanes[argIndex+1] ), \ + lanes2 = LOAD256( stateAsLanes[argIndex+2] ), \ + lanes3 = LOAD256( stateAsLanes[argIndex+3] ), \ + UNINTLEAVE(), \ + STORE256u( curData0[argIndex], lanes0 ), \ + STORE256u( curData1[argIndex], lanes1 ), \ + STORE256u( curData2[argIndex], lanes2 ), \ + STORE256u( curData3[argIndex], lanes3 ) + + if ( laneCount >= 16 ) { + Extr4( 0 ); + Extr4( 4 ); + Extr4( 8 ); + Extr4( 12 ); + if ( laneCount >= 20 ) { + Extr4( 16 ); + for(i=20; i 0) && (offsetInLane != 0)) { + unsigned int bytesInLane = SnP_laneLengthInBytes - offsetInLane; + UINT64 lane = statesAsLanes[laneIndex(instanceIndex, lanePosition)] >> (8 * offsetInLane); + if (bytesInLane > sizeLeft) + bytesInLane = sizeLeft; + sizeLeft -= bytesInLane; + do { + *(curOutput++) = *(curInput++) ^ (unsigned char)lane; + lane >>= 8; + } while ( --bytesInLane != 0); + lanePosition++; + } + + while(sizeLeft >= SnP_laneLengthInBytes) { + *((UINT64*)curOutput) = *((UINT64*)curInput) ^ statesAsLanes[laneIndex(instanceIndex, lanePosition)]; + sizeLeft -= SnP_laneLengthInBytes; + lanePosition++; + curInput += SnP_laneLengthInBytes; + curOutput += SnP_laneLengthInBytes; + } + + if (sizeLeft != 0) { + UINT64 lane = statesAsLanes[laneIndex(instanceIndex, lanePosition)]; + do { + *(curOutput++) = *(curInput++) ^ (unsigned char)lane; + lane >>= 8; + } while ( --sizeLeft != 0); + } +} + +void KeccakP1600times4_ExtractAndAddLanesAll(const void *states, const unsigned char *input, unsigned char *output, unsigned int laneCount, unsigned int laneOffset) +{ + const UINT64 *curInput0 = (UINT64 *)input; + const UINT64 *curInput1 = (UINT64 *)(input+laneOffset*1*SnP_laneLengthInBytes); + const UINT64 *curInput2 = (UINT64 *)(input+laneOffset*2*SnP_laneLengthInBytes); + const UINT64 *curInput3 = (UINT64 *)(input+laneOffset*3*SnP_laneLengthInBytes); + UINT64 *curOutput0 = (UINT64 *)output; + UINT64 *curOutput1 = (UINT64 *)(output+laneOffset*1*SnP_laneLengthInBytes); + UINT64 *curOutput2 = (UINT64 *)(output+laneOffset*2*SnP_laneLengthInBytes); + UINT64 *curOutput3 = (UINT64 *)(output+laneOffset*3*SnP_laneLengthInBytes); + + const V256 *stateAsLanes = (const V256 *)states; + const UINT64 *stateAsLanes64 = (const UINT64*)states; + V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; + unsigned int i; + + #define ExtrXor( argIndex ) \ + curOutput0[argIndex] = curInput0[argIndex] ^ stateAsLanes64[4*(argIndex)],\ + curOutput1[argIndex] = curInput1[argIndex] ^ stateAsLanes64[4*(argIndex)+1],\ + curOutput2[argIndex] = curInput2[argIndex] ^ stateAsLanes64[4*(argIndex)+2],\ + curOutput3[argIndex] = curInput3[argIndex] ^ stateAsLanes64[4*(argIndex)+3] + + #define ExtrXor4( argIndex ) \ + lanes0 = LOAD256( stateAsLanes[argIndex+0] ),\ + lanes1 = LOAD256( stateAsLanes[argIndex+1] ),\ + lanes2 = LOAD256( stateAsLanes[argIndex+2] ),\ + lanes3 = LOAD256( stateAsLanes[argIndex+3] ),\ + UNINTLEAVE(),\ + lanesL01 = LOAD256u( curInput0[argIndex]),\ + lanesH01 = LOAD256u( curInput1[argIndex]),\ + lanesL23 = LOAD256u( curInput2[argIndex]),\ + lanesH23 = LOAD256u( curInput3[argIndex]),\ + XOReq256( lanes0, lanesL01 ),\ + XOReq256( lanes1, lanesH01 ),\ + XOReq256( lanes2, lanesL23 ),\ + XOReq256( lanes3, lanesH23 ),\ + STORE256u( curOutput0[argIndex], lanes0 ),\ + STORE256u( curOutput1[argIndex], lanes1 ),\ + STORE256u( curOutput2[argIndex], lanes2 ),\ + STORE256u( curOutput3[argIndex], lanes3 ) + + if ( laneCount >= 16 ) { + ExtrXor4( 0 ); + ExtrXor4( 4 ); + ExtrXor4( 8 ); + ExtrXor4( 12 ); + if ( laneCount >= 20 ) { + ExtrXor4( 16 ); + for(i=20; i= (laneOffsetParallel*3 + laneCount)*8) { + V256 *stateAsLanes = (V256 *)states; + V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; + #define Xor_In( argIndex ) \ + XOReq256(stateAsLanes[argIndex], LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) + #define Xor_In4( argIndex ) \ + lanes0 = LOAD256u( curData0[argIndex]),\ + lanes1 = LOAD256u( curData1[argIndex]),\ + lanes2 = LOAD256u( curData2[argIndex]),\ + lanes3 = LOAD256u( curData3[argIndex]),\ + INTLEAVE(),\ + XOReq256( stateAsLanes[argIndex+0], lanes0 ),\ + XOReq256( stateAsLanes[argIndex+1], lanes1 ),\ + XOReq256( stateAsLanes[argIndex+2], lanes2 ),\ + XOReq256( stateAsLanes[argIndex+3], lanes3 ) + Xor_In4( 0 ); + Xor_In4( 4 ); + Xor_In4( 8 ); + Xor_In4( 12 ); + Xor_In4( 16 ); + Xor_In( 20 ); + #undef Xor_In + #undef Xor_In4 + KeccakP1600times4_PermuteAll_24rounds(states); + curData0 += laneOffsetSerial; + curData1 += laneOffsetSerial; + curData2 += laneOffsetSerial; + curData3 += laneOffsetSerial; + dataByteLen -= laneOffsetSerial*8; + } + return (const unsigned char *)curData0 - dataStart; +#else +// unsigned int i; + const unsigned char *dataStart = data; + const UINT64 *curData0 = (const UINT64 *)data; + const UINT64 *curData1 = (const UINT64 *)(data+laneOffsetParallel*1*SnP_laneLengthInBytes); + const UINT64 *curData2 = (const UINT64 *)(data+laneOffsetParallel*2*SnP_laneLengthInBytes); + const UINT64 *curData3 = (const UINT64 *)(data+laneOffsetParallel*3*SnP_laneLengthInBytes); + V256 *statesAsLanes = (V256 *)states; + declareABCDE + + copyFromState(A, statesAsLanes) + while(dataByteLen >= (laneOffsetParallel*3 + laneCount)*8) { + #define XOR_In( Xxx, argIndex ) \ + XOReq256(Xxx, LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) + XOR_In( Aba, 0 ); + XOR_In( Abe, 1 ); + XOR_In( Abi, 2 ); + XOR_In( Abo, 3 ); + XOR_In( Abu, 4 ); + XOR_In( Aga, 5 ); + XOR_In( Age, 6 ); + XOR_In( Agi, 7 ); + XOR_In( Ago, 8 ); + XOR_In( Agu, 9 ); + XOR_In( Aka, 10 ); + XOR_In( Ake, 11 ); + XOR_In( Aki, 12 ); + XOR_In( Ako, 13 ); + XOR_In( Aku, 14 ); + XOR_In( Ama, 15 ); + XOR_In( Ame, 16 ); + XOR_In( Ami, 17 ); + XOR_In( Amo, 18 ); + XOR_In( Amu, 19 ); + XOR_In( Asa, 20 ); + #undef XOR_In + rounds24 + curData0 += laneOffsetSerial; + curData1 += laneOffsetSerial; + curData2 += laneOffsetSerial; + curData3 += laneOffsetSerial; + dataByteLen -= laneOffsetSerial*8; + } + copyToState(statesAsLanes, A) + return (const unsigned char *)curData0 - dataStart; +#endif + } + else { +// unsigned int i; + const unsigned char *dataStart = data; + + while(dataByteLen >= (laneOffsetParallel*3 + laneCount)*8) { + KeccakP1600times4_AddLanesAll(states, data, laneCount, laneOffsetParallel); + KeccakP1600times4_PermuteAll_24rounds(states); + data += laneOffsetSerial*8; + dataByteLen -= laneOffsetSerial*8; + } + return data - dataStart; + } +} + +size_t KeccakP1600times4_12rounds_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen) +{ + if (laneCount == 21) { +#if 0 + const unsigned char *dataStart = data; + const UINT64 *curData0 = (const UINT64 *)data; + const UINT64 *curData1 = (const UINT64 *)(data+laneOffsetParallel*1*SnP_laneLengthInBytes); + const UINT64 *curData2 = (const UINT64 *)(data+laneOffsetParallel*2*SnP_laneLengthInBytes); + const UINT64 *curData3 = (const UINT64 *)(data+laneOffsetParallel*3*SnP_laneLengthInBytes); + + while(dataByteLen >= (laneOffsetParallel*3 + laneCount)*8) { + V256 *stateAsLanes = states; + V256 lanes0, lanes1, lanes2, lanes3, lanesL01, lanesL23, lanesH01, lanesH23; + #define Xor_In( argIndex ) \ + XOReq256(stateAsLanes[argIndex], LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) + #define Xor_In4( argIndex ) \ + lanes0 = LOAD256u( curData0[argIndex]),\ + lanes1 = LOAD256u( curData1[argIndex]),\ + lanes2 = LOAD256u( curData2[argIndex]),\ + lanes3 = LOAD256u( curData3[argIndex]),\ + INTLEAVE(),\ + XOReq256( stateAsLanes[argIndex+0], lanes0 ),\ + XOReq256( stateAsLanes[argIndex+1], lanes1 ),\ + XOReq256( stateAsLanes[argIndex+2], lanes2 ),\ + XOReq256( stateAsLanes[argIndex+3], lanes3 ) + Xor_In4( 0 ); + Xor_In4( 4 ); + Xor_In4( 8 ); + Xor_In4( 12 ); + Xor_In4( 16 ); + Xor_In( 20 ); + #undef Xor_In + #undef Xor_In4 + KeccakP1600times4_PermuteAll_12rounds(states); + curData0 += laneOffsetSerial; + curData1 += laneOffsetSerial; + curData2 += laneOffsetSerial; + curData3 += laneOffsetSerial; + dataByteLen -= laneOffsetSerial*8; + } + return (const unsigned char *)curData0 - dataStart; +#else +// unsigned int i; + const unsigned char *dataStart = data; + const UINT64 *curData0 = (const UINT64 *)data; + const UINT64 *curData1 = (const UINT64 *)(data+laneOffsetParallel*1*SnP_laneLengthInBytes); + const UINT64 *curData2 = (const UINT64 *)(data+laneOffsetParallel*2*SnP_laneLengthInBytes); + const UINT64 *curData3 = (const UINT64 *)(data+laneOffsetParallel*3*SnP_laneLengthInBytes); + V256 *statesAsLanes = states; + declareABCDE + + copyFromState(A, statesAsLanes) + while(dataByteLen >= (laneOffsetParallel*3 + laneCount)*8) { + #define XOR_In( Xxx, argIndex ) \ + XOReq256(Xxx, LOAD4_64(curData3[argIndex], curData2[argIndex], curData1[argIndex], curData0[argIndex])) + XOR_In( Aba, 0 ); + XOR_In( Abe, 1 ); + XOR_In( Abi, 2 ); + XOR_In( Abo, 3 ); + XOR_In( Abu, 4 ); + XOR_In( Aga, 5 ); + XOR_In( Age, 6 ); + XOR_In( Agi, 7 ); + XOR_In( Ago, 8 ); + XOR_In( Agu, 9 ); + XOR_In( Aka, 10 ); + XOR_In( Ake, 11 ); + XOR_In( Aki, 12 ); + XOR_In( Ako, 13 ); + XOR_In( Aku, 14 ); + XOR_In( Ama, 15 ); + XOR_In( Ame, 16 ); + XOR_In( Ami, 17 ); + XOR_In( Amo, 18 ); + XOR_In( Amu, 19 ); + XOR_In( Asa, 20 ); + #undef XOR_In + rounds12 + curData0 += laneOffsetSerial; + curData1 += laneOffsetSerial; + curData2 += laneOffsetSerial; + curData3 += laneOffsetSerial; + dataByteLen -= laneOffsetSerial*8; + } + copyToState(statesAsLanes, A) + return (const unsigned char *)curData0 - dataStart; +#endif + } + else { +// unsigned int i; + const unsigned char *dataStart = data; + + while(dataByteLen >= (laneOffsetParallel*3 + laneCount)*8) { + KeccakP1600times4_AddLanesAll(states, data, laneCount, laneOffsetParallel); + KeccakP1600times4_PermuteAll_12rounds(states); + data += laneOffsetSerial*8; + dataByteLen -= laneOffsetSerial*8; + } + return data - dataStart; + } +} diff --git a/shake-avx2/keccak4x/KeccakP-1600-times4-SnP.h b/shake-avx2/keccak4x/KeccakP-1600-times4-SnP.h new file mode 100644 index 0000000..6033848 --- /dev/null +++ b/shake-avx2/keccak4x/KeccakP-1600-times4-SnP.h @@ -0,0 +1,50 @@ +/* +Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, +Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby +denoted as "the implementer". + +For more information, feedback or questions, please refer to our websites: +http://keccak.noekeon.org/ +http://keyak.noekeon.org/ +http://ketje.noekeon.org/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _KeccakP_1600_times4_SnP_h_ +#define _KeccakP_1600_times4_SnP_h_ + +/** For the documentation, see PlSnP-documentation.h. + */ + +#include "SIMD256-config.h" + +#define KeccakP1600times4_implementation "256-bit SIMD implementation (" KeccakP1600times4_implementation_config ")" +#define KeccakP1600times4_statesSizeInBytes 800 +#define KeccakP1600times4_statesAlignment 32 +#define KeccakF1600times4_FastLoop_supported +#define KeccakP1600times4_12rounds_FastLoop_supported + +#include + +#define KeccakP1600times4_StaticInitialize() +void KeccakP1600times4_InitializeAll(void *states); +#define KeccakP1600times4_AddByte(states, instanceIndex, byte, offset) \ + ((unsigned char*)(states))[(instanceIndex)*8 + ((offset)/8)*4*8 + (offset)%8] ^= (byte) +void KeccakP1600times4_AddBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length); +void KeccakP1600times4_AddLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset); +void KeccakP1600times4_OverwriteBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length); +void KeccakP1600times4_OverwriteLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset); +void KeccakP1600times4_OverwriteWithZeroes(void *states, unsigned int instanceIndex, unsigned int byteCount); +void KeccakP1600times4_PermuteAll_12rounds(void *states); +void KeccakP1600times4_PermuteAll_24rounds(void *states); +void KeccakP1600times4_ExtractBytes(const void *states, unsigned int instanceIndex, unsigned char *data, unsigned int offset, unsigned int length); +void KeccakP1600times4_ExtractLanesAll(const void *states, unsigned char *data, unsigned int laneCount, unsigned int laneOffset); +void KeccakP1600times4_ExtractAndAddBytes(const void *states, unsigned int instanceIndex, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length); +void KeccakP1600times4_ExtractAndAddLanesAll(const void *states, const unsigned char *input, unsigned char *output, unsigned int laneCount, unsigned int laneOffset); +size_t KeccakF1600times4_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen); +size_t KeccakP1600times4_12rounds_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen); + +#endif diff --git a/shake-avx2/keccak4x/KeccakP-1600-unrolling.macros b/shake-avx2/keccak4x/KeccakP-1600-unrolling.macros new file mode 100644 index 0000000..3180bb0 --- /dev/null +++ b/shake-avx2/keccak4x/KeccakP-1600-unrolling.macros @@ -0,0 +1,198 @@ +/* +Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, +Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby +denoted as "the implementer". + +For more information, feedback or questions, please refer to our websites: +http://keccak.noekeon.org/ +http://keyak.noekeon.org/ +http://ketje.noekeon.org/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#if (defined(FullUnrolling)) +#define rounds24 \ + prepareTheta \ + thetaRhoPiChiIotaPrepareTheta( 0, A, E) \ + thetaRhoPiChiIotaPrepareTheta( 1, E, A) \ + thetaRhoPiChiIotaPrepareTheta( 2, A, E) \ + thetaRhoPiChiIotaPrepareTheta( 3, E, A) \ + thetaRhoPiChiIotaPrepareTheta( 4, A, E) \ + thetaRhoPiChiIotaPrepareTheta( 5, E, A) \ + thetaRhoPiChiIotaPrepareTheta( 6, A, E) \ + thetaRhoPiChiIotaPrepareTheta( 7, E, A) \ + thetaRhoPiChiIotaPrepareTheta( 8, A, E) \ + thetaRhoPiChiIotaPrepareTheta( 9, E, A) \ + thetaRhoPiChiIotaPrepareTheta(10, A, E) \ + thetaRhoPiChiIotaPrepareTheta(11, E, A) \ + thetaRhoPiChiIotaPrepareTheta(12, A, E) \ + thetaRhoPiChiIotaPrepareTheta(13, E, A) \ + thetaRhoPiChiIotaPrepareTheta(14, A, E) \ + thetaRhoPiChiIotaPrepareTheta(15, E, A) \ + thetaRhoPiChiIotaPrepareTheta(16, A, E) \ + thetaRhoPiChiIotaPrepareTheta(17, E, A) \ + thetaRhoPiChiIotaPrepareTheta(18, A, E) \ + thetaRhoPiChiIotaPrepareTheta(19, E, A) \ + thetaRhoPiChiIotaPrepareTheta(20, A, E) \ + thetaRhoPiChiIotaPrepareTheta(21, E, A) \ + thetaRhoPiChiIotaPrepareTheta(22, A, E) \ + thetaRhoPiChiIota(23, E, A) \ + +#define rounds12 \ + prepareTheta \ + thetaRhoPiChiIotaPrepareTheta(12, A, E) \ + thetaRhoPiChiIotaPrepareTheta(13, E, A) \ + thetaRhoPiChiIotaPrepareTheta(14, A, E) \ + thetaRhoPiChiIotaPrepareTheta(15, E, A) \ + thetaRhoPiChiIotaPrepareTheta(16, A, E) \ + thetaRhoPiChiIotaPrepareTheta(17, E, A) \ + thetaRhoPiChiIotaPrepareTheta(18, A, E) \ + thetaRhoPiChiIotaPrepareTheta(19, E, A) \ + thetaRhoPiChiIotaPrepareTheta(20, A, E) \ + thetaRhoPiChiIotaPrepareTheta(21, E, A) \ + thetaRhoPiChiIotaPrepareTheta(22, A, E) \ + thetaRhoPiChiIota(23, E, A) \ + +#elif (Unrolling == 12) +#define rounds24 \ + prepareTheta \ + for(i=0; i<24; i+=12) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \ + } \ + +#define rounds12 \ + prepareTheta \ + thetaRhoPiChiIotaPrepareTheta(12, A, E) \ + thetaRhoPiChiIotaPrepareTheta(13, E, A) \ + thetaRhoPiChiIotaPrepareTheta(14, A, E) \ + thetaRhoPiChiIotaPrepareTheta(15, E, A) \ + thetaRhoPiChiIotaPrepareTheta(16, A, E) \ + thetaRhoPiChiIotaPrepareTheta(17, E, A) \ + thetaRhoPiChiIotaPrepareTheta(18, A, E) \ + thetaRhoPiChiIotaPrepareTheta(19, E, A) \ + thetaRhoPiChiIotaPrepareTheta(20, A, E) \ + thetaRhoPiChiIotaPrepareTheta(21, E, A) \ + thetaRhoPiChiIotaPrepareTheta(22, A, E) \ + thetaRhoPiChiIota(23, E, A) \ + +#elif (Unrolling == 6) +#define rounds24 \ + prepareTheta \ + for(i=0; i<24; i+=6) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ + } \ + +#define rounds12 \ + prepareTheta \ + for(i=12; i<24; i+=6) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ + } \ + +#elif (Unrolling == 4) +#define rounds24 \ + prepareTheta \ + for(i=0; i<24; i+=4) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ + } \ + +#define rounds12 \ + prepareTheta \ + for(i=12; i<24; i+=4) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ + } \ + +#elif (Unrolling == 3) +#define rounds24 \ + prepareTheta \ + for(i=0; i<24; i+=3) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ + copyStateVariables(A, E) \ + } \ + +#define rounds12 \ + prepareTheta \ + for(i=12; i<24; i+=3) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ + copyStateVariables(A, E) \ + } \ + +#elif (Unrolling == 2) +#define rounds24 \ + prepareTheta \ + for(i=0; i<24; i+=2) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + } \ + +#define rounds12 \ + prepareTheta \ + for(i=12; i<24; i+=2) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + } \ + +#elif (Unrolling == 1) +#define rounds24 \ + prepareTheta \ + for(i=0; i<24; i++) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + copyStateVariables(A, E) \ + } \ + +#define rounds12 \ + prepareTheta \ + for(i=12; i<24; i++) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + copyStateVariables(A, E) \ + } \ + +#else +#error "Unrolling is not correctly specified!" +#endif + +#define roundsN(__nrounds) \ + prepareTheta \ + i = 24 - (__nrounds); \ + if ((i&1) != 0) { \ + thetaRhoPiChiIotaPrepareTheta(i, A, E) \ + copyStateVariables(A, E) \ + ++i; \ + } \ + for( /* empty */; i<24; i+=2) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + } diff --git a/shake-avx2/keccak4x/SIMD256-config.h b/shake-avx2/keccak4x/SIMD256-config.h new file mode 100644 index 0000000..1c65fe2 --- /dev/null +++ b/shake-avx2/keccak4x/SIMD256-config.h @@ -0,0 +1,3 @@ +#define KeccakP1600times4_implementation_config "AVX2, all rounds unrolled" +#define KeccakP1600times4_fullUnrolling +#define KeccakP1600times4_useAVX2 diff --git a/shake-avx2/keccak4x/align.h b/shake-avx2/keccak4x/align.h new file mode 100644 index 0000000..e29771e --- /dev/null +++ b/shake-avx2/keccak4x/align.h @@ -0,0 +1,34 @@ +/* +Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, +Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby +denoted as "the implementer". + +For more information, feedback or questions, please refer to our websites: +http://keccak.noekeon.org/ +http://keyak.noekeon.org/ +http://ketje.noekeon.org/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _align_h_ +#define _align_h_ + +/* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */ +#ifdef ALIGN +#undef ALIGN +#endif + +#if defined(__GNUC__) +#define ALIGN(x) __attribute__ ((aligned(x))) +#elif defined(_MSC_VER) +#define ALIGN(x) __declspec(align(x)) +#elif defined(__ARMCC_VERSION) +#define ALIGN(x) __align(x) +#else +#define ALIGN(x) +#endif + +#endif diff --git a/shake-avx2/keccak4x/brg_endian.h b/shake-avx2/keccak4x/brg_endian.h new file mode 100644 index 0000000..7226eb3 --- /dev/null +++ b/shake-avx2/keccak4x/brg_endian.h @@ -0,0 +1,142 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 + Changes for ARM 9/9/2010 +*/ + +#ifndef _BRG_ENDIAN_H +#define _BRG_ENDIAN_H + +#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ +#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ + +#if 0 +/* Include files where endian defines and byteswap functions may reside */ +#if defined( __sun ) +# include +#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) +# include +#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \ + defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ ) +# include +#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ ) +# if !defined( __MINGW32__ ) && !defined( _AIX ) +# include +# if !defined( __BEOS__ ) +# include +# endif +# endif +#endif +#endif + +/* Now attempt to set the define for platform byte order using any */ +/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */ +/* seem to encompass most endian symbol definitions */ + +#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN ) +# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN ) +# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( _BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( _LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN ) +# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( __BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( __LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ ) +# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( __BIG_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( __LITTLE_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +/* if the platform byte order could not be determined, then try to */ +/* set this define using common machine defines */ +#if !defined(PLATFORM_BYTE_ORDER) + +#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \ + defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \ + defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \ + defined( vax ) || defined( vms ) || defined( VMS ) || \ + defined( __VMS ) || defined( _M_X64 ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN + +#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \ + defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \ + defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \ + defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \ + defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \ + defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \ + defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN + +#elif defined(__arm__) +# ifdef __BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# else +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif 1 /* **** EDIT HERE IF NECESSARY **** */ +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#else +# error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order +#endif + +#endif + +#endif diff --git a/shake-avx2/merkle.c b/shake-avx2/merkle.c new file mode 100644 index 0000000..e3929d8 --- /dev/null +++ b/shake-avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" +#include "merkle.h" +#include "address.h" +#include "params.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx* ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) +{ + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4*8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j=0; j<4; j++) { + set_type(&tree_addrx4[8*j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8*j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8*j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8*j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8*j], wots_addr); + copy_subtree_addr(&info.pk_addr[8*j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) +{ + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/shake-avx2/merkle.h b/shake-avx2/merkle.h new file mode 120000 index 0000000..7d167ed --- /dev/null +++ b/shake-avx2/merkle.h @@ -0,0 +1 @@ +../ref/merkle.h \ No newline at end of file diff --git a/shake-avx2/params.h b/shake-avx2/params.h new file mode 120000 index 0000000..53133cc --- /dev/null +++ b/shake-avx2/params.h @@ -0,0 +1 @@ +../ref/params.h \ No newline at end of file diff --git a/shake-avx2/params/params-sphincs-shake-128f.h b/shake-avx2/params/params-sphincs-shake-128f.h new file mode 120000 index 0000000..c65db98 --- /dev/null +++ b/shake-avx2/params/params-sphincs-shake-128f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-128f.h \ No newline at end of file diff --git a/shake-avx2/params/params-sphincs-shake-128s.h b/shake-avx2/params/params-sphincs-shake-128s.h new file mode 120000 index 0000000..18671f7 --- /dev/null +++ b/shake-avx2/params/params-sphincs-shake-128s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-128s.h \ No newline at end of file diff --git a/shake-avx2/params/params-sphincs-shake-192f.h b/shake-avx2/params/params-sphincs-shake-192f.h new file mode 120000 index 0000000..d071e35 --- /dev/null +++ b/shake-avx2/params/params-sphincs-shake-192f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-192f.h \ No newline at end of file diff --git a/shake-avx2/params/params-sphincs-shake-192s.h b/shake-avx2/params/params-sphincs-shake-192s.h new file mode 120000 index 0000000..267e2c8 --- /dev/null +++ b/shake-avx2/params/params-sphincs-shake-192s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-192s.h \ No newline at end of file diff --git a/shake-avx2/params/params-sphincs-shake-256f.h b/shake-avx2/params/params-sphincs-shake-256f.h new file mode 120000 index 0000000..3b4743b --- /dev/null +++ b/shake-avx2/params/params-sphincs-shake-256f.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-256f.h \ No newline at end of file diff --git a/shake-avx2/params/params-sphincs-shake-256s.h b/shake-avx2/params/params-sphincs-shake-256s.h new file mode 120000 index 0000000..0795ee1 --- /dev/null +++ b/shake-avx2/params/params-sphincs-shake-256s.h @@ -0,0 +1 @@ +../../ref/params/params-sphincs-shake-256s.h \ No newline at end of file diff --git a/shake-avx2/randombytes.c b/shake-avx2/randombytes.c new file mode 120000 index 0000000..59a42a5 --- /dev/null +++ b/shake-avx2/randombytes.c @@ -0,0 +1 @@ +../ref/randombytes.c \ No newline at end of file diff --git a/shake-avx2/randombytes.h b/shake-avx2/randombytes.h new file mode 120000 index 0000000..055e443 --- /dev/null +++ b/shake-avx2/randombytes.h @@ -0,0 +1 @@ +../ref/randombytes.h \ No newline at end of file diff --git a/shake-avx2/rng.c b/shake-avx2/rng.c new file mode 120000 index 0000000..6e2fdac --- /dev/null +++ b/shake-avx2/rng.c @@ -0,0 +1 @@ +../ref/rng.c \ No newline at end of file diff --git a/shake-avx2/rng.h b/shake-avx2/rng.h new file mode 120000 index 0000000..d678c7c --- /dev/null +++ b/shake-avx2/rng.h @@ -0,0 +1 @@ +../ref/rng.h \ No newline at end of file diff --git a/shake-avx2/shake_offsets.h b/shake-avx2/shake_offsets.h new file mode 120000 index 0000000..8cfe4c0 --- /dev/null +++ b/shake-avx2/shake_offsets.h @@ -0,0 +1 @@ +../ref/shake_offsets.h \ No newline at end of file diff --git a/shake-avx2/sign.c b/shake-avx2/sign.c new file mode 120000 index 0000000..42fea88 --- /dev/null +++ b/shake-avx2/sign.c @@ -0,0 +1 @@ +../ref/sign.c \ No newline at end of file diff --git a/shake-avx2/test/benchmark.c b/shake-avx2/test/benchmark.c new file mode 100644 index 0000000..a5767a4 --- /dev/null +++ b/shake-avx2/test/benchmark.c @@ -0,0 +1,161 @@ +#define _POSIX_C_SOURCE 199309L + +#include +#include +#include + +#include "../api.h" +#include "../fors.h" +#include "../wots.h" +#include "../wotsx4.h" +#include "../params.h" +#include "../randombytes.h" + +#define SPX_MLEN 32 +#define NTESTS 10 + +static void wots_gen_pkx4(unsigned char *pk, const spx_ctx *ctx, + uint32_t addr[8]); + +static int cmp_llu(const void *a, const void*b) +{ + if(*(unsigned long long *)a < *(unsigned long long *)b) return -1; + if(*(unsigned long long *)a > *(unsigned long long *)b) return 1; + return 0; +} + +static unsigned long long median(unsigned long long *l, size_t llen) +{ + qsort(l,llen,sizeof(unsigned long long),cmp_llu); + + if(llen%2) return l[llen/2]; + else return (l[llen/2-1]+l[llen/2])/2; +} + +static void delta(unsigned long long *l, size_t llen) +{ + unsigned int i; + for(i = 0; i < llen - 1; i++) { + l[i] = l[i+1] - l[i]; + } +} + +static unsigned long long cpucycles(void) +{ + unsigned long long result; + __asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax" + : "=a" (result) :: "%rdx"); + return result; +} + +static void printfcomma (unsigned long long n) +{ + if (n < 1000) { + printf("%llu", n); + return; + } + printfcomma(n / 1000); + printf (",%03llu", n % 1000); +} + +static void printfalignedcomma (unsigned long long n, int len) +{ + unsigned long long ncopy = n; + int i = 0; + + while (ncopy > 9) { + len -= 1; + ncopy /= 10; + i += 1; // to account for commas + } + i = i/3 - 1; // to account for commas + for (; i < len; i++) { + printf(" "); + } + printfcomma(n); +} + +static void display_result(double result, unsigned long long *l, size_t llen, unsigned long long mul) +{ + unsigned long long med; + + result /= NTESTS; + delta(l, NTESTS + 1); + med = median(l, llen); + printf("avg. %11.2lf us (%2.2lf sec); median ", result, result / 1e6); + printfalignedcomma(med, 12); + printf(" cycles, %5llux: ", mul); + printfalignedcomma(mul*med, 12); + printf(" cycles\n"); +} + +#define MEASURE(TEXT, MUL, FNCALL)\ + printf(TEXT);\ + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);\ + for(i = 0; i < NTESTS; i++) {\ + t[i] = cpucycles();\ + FNCALL;\ + }\ + t[NTESTS] = cpucycles();\ + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &stop);\ + result = (stop.tv_sec - start.tv_sec) * 1e6 + (stop.tv_nsec - start.tv_nsec) / 1e3;\ + display_result(result, t, NTESTS, MUL); + +int main(void) +{ + /* Make stdout buffer more responsive. */ + setbuf(stdout, NULL); + + spx_ctx ctx; + unsigned char pk[SPX_PK_BYTES]; + unsigned char sk[SPX_SK_BYTES]; + unsigned char *m = malloc(SPX_MLEN); + unsigned char *sm = malloc(SPX_BYTES + SPX_MLEN); + unsigned char *mout = malloc(SPX_BYTES + SPX_MLEN); + + unsigned char fors_pk[SPX_FORS_PK_BYTES]; + unsigned char fors_m[SPX_FORS_MSG_BYTES]; + unsigned char fors_sig[SPX_FORS_BYTES]; + unsigned char addr[SPX_ADDR_BYTES]; + unsigned char wots_pk[4*SPX_WOTS_PK_BYTES]; + + unsigned long long smlen; + unsigned long long mlen; + unsigned long long t[NTESTS+1]; + struct timespec start, stop; + double result; + int i; + + randombytes(m, SPX_MLEN); + randombytes(addr, SPX_ADDR_BYTES); + + printf("Parameters: n = %d, h = %d, d = %d, b = %d, k = %d, w = %d\n", + SPX_N, SPX_FULL_HEIGHT, SPX_D, SPX_FORS_HEIGHT, SPX_FORS_TREES, + SPX_WOTS_W); + + printf("Running %d iterations.\n", NTESTS); + + MEASURE("Generating keypair.. ", 1, crypto_sign_keypair(pk, sk)); + MEASURE(" - WOTS pk gen 4x.. ", (1 << SPX_TREE_HEIGHT) / 4, wots_gen_pkx4(wots_pk, &ctx, (uint32_t *) addr)); + MEASURE("Signing.. ", 1, crypto_sign(sm, &smlen, m, SPX_MLEN, sk)); + MEASURE(" - FORS signing.. ", 1, fors_sign(fors_sig, fors_pk, fors_m, &ctx, (uint32_t *) addr)); + MEASURE(" - WOTS pk gen x4.. ", SPX_D * (1 << SPX_TREE_HEIGHT) / 4, wots_gen_pkx4(wots_pk, &ctx, (uint32_t *) addr)); + MEASURE("Verifying.. ", 1, crypto_sign_open(mout, &mlen, sm, smlen, pk)); + + printf("Signature size: %d (%.2f KiB)\n", SPX_BYTES, SPX_BYTES / 1024.0); + printf("Public key size: %d (%.2f KiB)\n", SPX_PK_BYTES, SPX_PK_BYTES / 1024.0); + printf("Secret key size: %d (%.2f KiB)\n", SPX_SK_BYTES, SPX_SK_BYTES / 1024.0); + + free(m); + free(sm); + free(mout); + + return 0; +} + +static void wots_gen_pkx4(unsigned char *pk, const spx_ctx *ctx, uint32_t addr[8]) { + struct leaf_info_x4 leaf; + unsigned steps[ SPX_WOTS_LEN ] = { 0 }; + INITIALIZE_LEAF_INFO_X4(leaf, addr, steps); + wots_gen_leafx4(pk, ctx, 0, &leaf); +} diff --git a/shake-avx2/test/fors.c b/shake-avx2/test/fors.c new file mode 120000 index 0000000..b2bccee --- /dev/null +++ b/shake-avx2/test/fors.c @@ -0,0 +1 @@ +../../ref/test/fors.c \ No newline at end of file diff --git a/shake-avx2/test/spx.c b/shake-avx2/test/spx.c new file mode 120000 index 0000000..7af26df --- /dev/null +++ b/shake-avx2/test/spx.c @@ -0,0 +1 @@ +../../ref/test/spx.c \ No newline at end of file diff --git a/shake-avx2/test/thashx4.c b/shake-avx2/test/thashx4.c new file mode 100644 index 0000000..54e96f9 --- /dev/null +++ b/shake-avx2/test/thashx4.c @@ -0,0 +1,47 @@ +#include +#include + +#include "../thashx4.h" +#include "../thash.h" +#include "../randombytes.h" +#include "../params.h" + +int main(void) +{ + /* Make stdout buffer more responsive. */ + setbuf(stdout, NULL); + + unsigned char input[4*SPX_N]; + unsigned char output[4*SPX_N]; + unsigned char out4[4*SPX_N]; + uint32_t addr[4*8] = {0}; + unsigned int j; + spx_ctx ctx; + + randombytes(ctx.pub_seed, SPX_N); + randombytes(input, 4*SPX_N); + randombytes((unsigned char *)addr, 4 * 8 * sizeof(uint32_t)); + + printf("Testing if thash matches thashx4.. "); + + for (j = 0; j < 4; j++) { + thash(out4 + j * SPX_N, input + j * SPX_N, 1, &ctx, addr + j*8); + } + + thashx4(output + 0*SPX_N, + output + 1*SPX_N, + output + 2*SPX_N, + output + 3*SPX_N, + input + 0*SPX_N, + input + 1*SPX_N, + input + 2*SPX_N, + input + 3*SPX_N, + 1, &ctx, addr); + + if (memcmp(out4, output, 4 * SPX_N)) { + printf("failed!\n"); + return -1; + } + printf("successful.\n"); + return 0; +} diff --git a/shake-avx2/thash.h b/shake-avx2/thash.h new file mode 120000 index 0000000..937dd48 --- /dev/null +++ b/shake-avx2/thash.h @@ -0,0 +1 @@ +../ref/thash.h \ No newline at end of file diff --git a/shake-avx2/thash_shake_robust.c b/shake-avx2/thash_shake_robust.c new file mode 120000 index 0000000..3be16c6 --- /dev/null +++ b/shake-avx2/thash_shake_robust.c @@ -0,0 +1 @@ +../ref/thash_shake_robust.c \ No newline at end of file diff --git a/shake-avx2/thash_shake_robustx4.c b/shake-avx2/thash_shake_robustx4.c new file mode 100644 index 0000000..ba136a6 --- /dev/null +++ b/shake-avx2/thash_shake_robustx4.c @@ -0,0 +1,131 @@ +#include +#include + +#include "thashx4.h" +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4*8]) +{ + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N/8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t*)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N/8+i] = _mm256_set_epi32( + addrx4[3*8+1+2*i], + addrx4[3*8+2*i], + addrx4[2*8+1+2*i], + addrx4[2*8+2*i], + addrx4[8+1+2*i], + addrx4[8+2*i], + addrx4[1+2*i], + addrx4[2*i] + ); + } + + /* SHAKE domain separator and padding */ + state[SPX_N/8+4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N/8+5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + /* We will permutate state2 with f1600x4 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is alsmost identical. */ + __m256i state2[25]; + memcpy(state2, state, 800); + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + /* By copying from state, state2 already contains the pub_seed + * and addres. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N/8) * inblocks; i++) { + state2[SPX_N/8+4+i] = _mm256_xor_si256( + state[i], + _mm256_set_epi64x( + ((int64_t*)in3)[i], + ((int64_t*)in2)[i], + ((int64_t*)in1)[i], + ((int64_t*)in0)[i] + ) + ); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[(SPX_N/8)*(1+inblocks)+4] = _mm256_xor_si256( + state2[(SPX_N/8)*(1+inblocks)+4], + _mm256_set1_epi64x(0x1f) + ); + + KeccakP1600times4_PermuteAll_24rounds(&state2[0]); + + for (int i = 0; i < SPX_N/8; i++) { + ((int64_t*)out0)[i] = _mm256_extract_epi64(state2[i], 0); + ((int64_t*)out1)[i] = _mm256_extract_epi64(state2[i], 1); + ((int64_t*)out2)[i] = _mm256_extract_epi64(state2[i], 2); + ((int64_t*)out3)[i] = _mm256_extract_epi64(state2[i], 3); + } + } else { + SPX_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, bitmask0, inblocks * SPX_N); + SPX_VLA(unsigned char, bitmask1, inblocks * SPX_N); + SPX_VLA(unsigned char, bitmask2, inblocks * SPX_N); + SPX_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0*8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1*8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2*8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3*8, SPX_ADDR_BYTES); + + shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + } +} diff --git a/shake-avx2/thash_shake_simple.c b/shake-avx2/thash_shake_simple.c new file mode 120000 index 0000000..1b5a5a2 --- /dev/null +++ b/shake-avx2/thash_shake_simple.c @@ -0,0 +1 @@ +../ref/thash_shake_simple.c \ No newline at end of file diff --git a/shake-avx2/thash_shake_simplex4.c b/shake-avx2/thash_shake_simplex4.c new file mode 100644 index 0000000..3763ed1 --- /dev/null +++ b/shake-avx2/thash_shake_simplex4.c @@ -0,0 +1,98 @@ +#include +#include + +#include "thashx4.h" +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4*8]) +{ + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N/8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t*)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N/8+i] = _mm256_set_epi32( + addrx4[3*8+1+2*i], + addrx4[3*8+2*i], + addrx4[2*8+1+2*i], + addrx4[2*8+2*i], + addrx4[8+1+2*i], + addrx4[8+2*i], + addrx4[1+2*i], + addrx4[2*i] + ); + } + + for (unsigned int i = 0; i < (SPX_N/8) * inblocks; i++) { + state[SPX_N/8+4+i] = _mm256_set_epi64x( + ((int64_t*)in3)[i], + ((int64_t*)in2)[i], + ((int64_t*)in1)[i], + ((int64_t*)in0)[i] + ); + } + + /* Domain separator and padding. */ + for (int i = (SPX_N/8)*(1+inblocks)+4; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + state[(SPX_N/8)*(1+inblocks)+4] = _mm256_xor_si256( + state[(SPX_N/8)*(1+inblocks)+4], + _mm256_set1_epi64x(0x1f) + ); + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N/8; i++) { + ((int64_t*)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t*)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t*)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t*)out3)[i] = _mm256_extract_epi64(state[i], 3); + } + } else { + SPX_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + SPX_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0*8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1*8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2*8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3*8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_N + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_N + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks*SPX_N); + } +} diff --git a/shake-avx2/thashx4.h b/shake-avx2/thashx4.h new file mode 100644 index 0000000..045237e --- /dev/null +++ b/shake-avx2/thashx4.h @@ -0,0 +1,19 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4*8]); + +#endif diff --git a/shake-avx2/utils.c b/shake-avx2/utils.c new file mode 120000 index 0000000..e8ef6eb --- /dev/null +++ b/shake-avx2/utils.c @@ -0,0 +1 @@ +../ref/utils.c \ No newline at end of file diff --git a/shake-avx2/utils.h b/shake-avx2/utils.h new file mode 120000 index 0000000..51b0d39 --- /dev/null +++ b/shake-avx2/utils.h @@ -0,0 +1 @@ +../ref/utils.h \ No newline at end of file diff --git a/shake-avx2/utilsx4.c b/shake-avx2/utilsx4.c new file mode 100644 index 0000000..4d69825 --- /dev/null +++ b/shake-avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utils.h" +#include "utilsx4.h" +#include "params.h" +#include "thashx4.h" +#include "address.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char* /* Where to write the leaves */, + const spx_ctx*, + uint32_t idx, void *info), + uint32_t tree_addrx4[4*8], + void *info) +{ + /* This is where we keep the intermediate nodes */ + SPX_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height-2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4*SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4*idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h=0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3*SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3*SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf&3)^1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j*8, h + 1); + set_tree_index(tree_addrx4 + j*8, + (4/2) * (internal_idx&~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/shake-avx2/utilsx4.h b/shake-avx2/utilsx4.h new file mode 100644 index 0000000..92e0a4a --- /dev/null +++ b/shake-avx2/utilsx4.h @@ -0,0 +1,28 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char* /* Where to write the leaves */, + const spx_ctx* /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4*8], void *info); + +#endif diff --git a/shake-avx2/wots.c b/shake-avx2/wots.c new file mode 100644 index 0000000..0788b80 --- /dev/null +++ b/shake-avx2/wots.c @@ -0,0 +1,271 @@ +#include +#include + +#include "utils.h" +#include "utilsx4.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "wots.h" +#include "wotsx4.h" +#include "address.h" +#include "params.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) +{ + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8*4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs+j*8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN*SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i+j < SPX_WOTS_LEN; j++) { + idx = idxs[i+j]; + set_chain_addr(addrs+j*8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i+watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs+j*8, k + start[idxs[i+j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) +{ + int in = 0; + int out = 0; + unsigned char total; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) +{ + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) +{ + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) +{ + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j*8, leaf_idx + j ); + set_keypair_addr( pk_addr + j*8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j*8, i); + set_hash_addr(leaf_addr + j*8, 0); + set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0*wots_offset, + buffer + 1*wots_offset, + buffer + 2*wots_offset, + buffer + 3*wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j*8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k=0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index*wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) break; + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j*8, k); + } + thashx4(buffer + 0*wots_offset, + buffer + 1*wots_offset, + buffer + 2*wots_offset, + buffer + 3*wots_offset, + buffer + 0*wots_offset, + buffer + 1*wots_offset, + buffer + 2*wots_offset, + buffer + 3*wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0*SPX_N, + dest + 1*SPX_N, + dest + 2*SPX_N, + dest + 3*SPX_N, + pk_buffer + 0*wots_offset, + pk_buffer + 1*wots_offset, + pk_buffer + 2*wots_offset, + pk_buffer + 3*wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/shake-avx2/wots.h b/shake-avx2/wots.h new file mode 120000 index 0000000..8c327ea --- /dev/null +++ b/shake-avx2/wots.h @@ -0,0 +1 @@ +../ref/wots.h \ No newline at end of file diff --git a/shake-avx2/wotsx4.h b/shake-avx2/wotsx4.h new file mode 100644 index 0000000..2a311c5 --- /dev/null +++ b/shake-avx2/wotsx4.h @@ -0,0 +1,40 @@ +#if !defined( WOTSX4_H_ ) +#define WOTSX4_H_ + +#include +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4*8]; + uint32_t pk_addr[4*8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + info.wots_sig = 0; \ + info.wots_sign_leaf = ~0; \ + info.wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &info.leaf_addr[8*i], addr, 32 ); \ + memcpy( &info.pk_addr[8*i], addr, 32 ); \ + } \ +} + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/vectors.py b/vectors.py new file mode 100755 index 0000000..0e0b0df --- /dev/null +++ b/vectors.py @@ -0,0 +1,101 @@ +#! /usr/bin/env python3 + +# Without arguments, generates sha256 sums of NIST KAT response files +# for each of the instances (which should match SHA256SUMS.) +# +# With two arguments, checks whether the sha256 sum of the given +# generated NIST KAT response file is correct, e.g.: +# +# ./vectors.py sphincs-shake-128s-simple shake-avx2 + +import multiprocessing +import subprocess +import itertools +import tempfile +import hashlib +import shutil +import os +import sys + +fns = ['shake', 'sha2', 'haraka'] +options = ["f", "s"] +sizes = [128, 192, 256] +thashes = ['robust', 'simple'] + +def nameFor(fn, opt, size, thash): + return f"sphincs-{fn}-{size}{opt}-{thash}" + +def make(fn, opt, size, thash, bindir, impl): + name = nameFor(fn, opt, size, thash) + overrides = [f'PARAMS=sphincs-{fn}-{size}{opt}', 'THASH='+thash] + + sys.stderr.write(f"Compiling {name} …\n") + sys.stderr.flush() + + subprocess.run(["make", "-C", impl, "clean"] + overrides, + stdout=subprocess.DEVNULL, stderr=sys.stderr, check=True) + subprocess.run(["make", '-j', "-C", impl, "PQCgenKAT_sign"] + overrides, + stdout=subprocess.DEVNULL, stderr=sys.stderr, check=True) + + shutil.move( + os.path.join(impl, 'PQCgenKAT_sign'), + os.path.join(bindir, name), + ) + + return (name, size) + +def run(name_size, bindir): + name, size = name_size + rsp = f'PQCsignKAT_{size//2}.rsp' + req = f'PQCsignKAT_{size//2}.req' + + with tempfile.TemporaryDirectory() as rundir: + sys.stderr.write(f"Running {name} …\n") + sys.stderr.flush() + + subprocess.run([os.path.join(bindir, name)], + stdout=subprocess.DEVNULL, stderr=sys.stderr, cwd=rundir, check=True) + with open(os.path.join(rundir, rsp), 'rb') as f: + h = hashlib.sha256(f.read()).hexdigest() + return f"{h} {name}" + +def generate_sums(): + with tempfile.TemporaryDirectory() as bindir: + with multiprocessing.Pool() as pool: + name_sizes = [] + for fn in fns: + for opt, size, thash in itertools.product(options, sizes, thashes): + name_sizes.append(make(fn, opt, size, thash, bindir, 'ref')) + + res = pool.starmap(run, zip(name_sizes, [bindir]*len(name_sizes))) + res.sort() + print('\n'.join(res)) + +def check_sum(name, impl): + line = None + with tempfile.TemporaryDirectory() as bindir: + for fn in fns: + for opt, size, thash in itertools.product( + options, sizes, thashes): + if nameFor(fn, opt, size, thash) != name: + continue + name_size = make(fn, opt, size, thash, bindir, impl) + line = run(name_size, bindir) + break + if not line: + sys.stderr.write("No such instance\n") + sys.exit(1) + with open('SHA256SUMS', 'r') as f: + if f.read().find(line + '\n') == -1: + sys.stderr.write(f"Test vector mismatch: {line}\n") + sys.exit(2) + sys.stderr.write("ok\n") + +if __name__ == '__main__': + if len(sys.argv) <= 1: + generate_sums() + elif len(sys.argv) == 3: + check_sum(sys.argv[1], sys.argv[2]) + else: + sys.stderr.write("Expect two or no arguments\n") + sys.exit(3) From 462760465fde67d16942407f4420ed51a004ed45 Mon Sep 17 00:00:00 2001 From: notmike Date: Tue, 3 Feb 2026 00:20:12 -0700 Subject: [PATCH 3/7] Squashed 'dilithium/' content from commit 6e00625 git-subtree-dir: dilithium git-subtree-split: 6e00625c5b29f516c6de973fe2ee2fbb150973f9 --- .gitignore | 9 + .travis.yml | 33 + AUTHORS.md | 7 + Common_META.yml | 15 + Dilithium2_META.yml | 44 ++ Dilithium3_META.yml | 44 ++ Dilithium5_META.yml | 44 ++ LICENSE | 7 + README.md | 81 +++ SHA256SUMS | 3 + avx2/.gitignore | 2 + avx2/Makefile | 118 ++++ avx2/align.h | 19 + avx2/api.h | 100 +++ avx2/config.h | 27 + avx2/consts.c | 100 +++ avx2/consts.h | 38 ++ avx2/f1600x4.S | 909 +++++++++++++++++++++++++++ avx2/fips202.c | 1 + avx2/fips202.h | 57 ++ avx2/fips202x4.c | 196 ++++++ avx2/fips202x4.h | 91 +++ avx2/invntt.S | 240 ++++++++ avx2/ntt.S | 198 ++++++ avx2/ntt.h | 19 + avx2/packing.c | 1 + avx2/packing.h | 1 + avx2/params.h | 1 + avx2/pointwise.S | 213 +++++++ avx2/poly.c | 1128 ++++++++++++++++++++++++++++++++++ avx2/poly.h | 112 ++++ avx2/polyvec.c | 588 ++++++++++++++++++ avx2/polyvec.h | 105 ++++ avx2/randombytes.c | 1 + avx2/randombytes.h | 1 + avx2/rejsample.c | 476 ++++++++++++++ avx2/rejsample.h | 28 + avx2/rounding.c | 200 ++++++ avx2/rounding.h | 17 + avx2/shuffle.S | 54 ++ avx2/shuffle.inc | 25 + avx2/sign.c | 530 ++++++++++++++++ avx2/sign.h | 1 + avx2/symmetric-shake.c | 1 + avx2/symmetric.h | 26 + avx2/test/.gitignore | 10 + avx2/test/cpucycles.c | 1 + avx2/test/cpucycles.h | 1 + avx2/test/speed_print.c | 1 + avx2/test/speed_print.h | 1 + avx2/test/test_dilithium.c | 1 + avx2/test/test_mul.c | 1 + avx2/test/test_speed.c | 1 + avx2/test/test_vectors.c | 275 +++++++++ ref/.gitignore | 2 + ref/Makefile | 139 +++++ ref/api.h | 98 +++ ref/config.h | 27 + ref/fips202.c | 774 +++++++++++++++++++++++ ref/fips202.h | 57 ++ ref/nistkat/.gitignore | 3 + ref/nistkat/PQCgenKAT_sign.c | 261 ++++++++ ref/nistkat/rng.c | 222 +++++++ ref/nistkat/rng.h | 55 ++ ref/ntt.c | 98 +++ ref/ntt.h | 13 + ref/packing.c | 237 +++++++ ref/packing.h | 38 ++ ref/params.h | 80 +++ ref/poly.c | 907 +++++++++++++++++++++++++++ ref/poly.h | 79 +++ ref/polyvec.c | 389 ++++++++++++ ref/polyvec.h | 93 +++ ref/precomp.gp | 12 + ref/randombytes.c | 80 +++ ref/randombytes.h | 9 + ref/reduce.c | 69 +++ ref/reduce.h | 22 + ref/rounding.c | 102 +++ ref/rounding.h | 19 + ref/sign.c | 443 +++++++++++++ ref/sign.h | 56 ++ ref/symmetric-shake.c | 28 + ref/symmetric.h | 34 + ref/test/.gitignore | 10 + ref/test/cpucycles.c | 17 + ref/test/cpucycles.h | 33 + ref/test/speed_print.c | 51 ++ ref/test/speed_print.h | 9 + ref/test/test_dilithium.c | 69 +++ ref/test/test_mul.c | 60 ++ ref/test/test_speed.c | 87 +++ ref/test/test_vectors.c | 251 ++++++++ runlcov.sh | 21 + runtests.sh | 33 + 95 files changed, 11290 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 AUTHORS.md create mode 100644 Common_META.yml create mode 100644 Dilithium2_META.yml create mode 100644 Dilithium3_META.yml create mode 100644 Dilithium5_META.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 SHA256SUMS create mode 100644 avx2/.gitignore create mode 100644 avx2/Makefile create mode 100644 avx2/align.h create mode 100644 avx2/api.h create mode 100644 avx2/config.h create mode 100644 avx2/consts.c create mode 100644 avx2/consts.h create mode 100644 avx2/f1600x4.S create mode 120000 avx2/fips202.c create mode 100644 avx2/fips202.h create mode 100644 avx2/fips202x4.c create mode 100644 avx2/fips202x4.h create mode 100644 avx2/invntt.S create mode 100644 avx2/ntt.S create mode 100644 avx2/ntt.h create mode 120000 avx2/packing.c create mode 120000 avx2/packing.h create mode 120000 avx2/params.h create mode 100644 avx2/pointwise.S create mode 100644 avx2/poly.c create mode 100644 avx2/poly.h create mode 100644 avx2/polyvec.c create mode 100644 avx2/polyvec.h create mode 120000 avx2/randombytes.c create mode 120000 avx2/randombytes.h create mode 100644 avx2/rejsample.c create mode 100644 avx2/rejsample.h create mode 100644 avx2/rounding.c create mode 100644 avx2/rounding.h create mode 100644 avx2/shuffle.S create mode 100644 avx2/shuffle.inc create mode 100644 avx2/sign.c create mode 120000 avx2/sign.h create mode 120000 avx2/symmetric-shake.c create mode 100644 avx2/symmetric.h create mode 100644 avx2/test/.gitignore create mode 120000 avx2/test/cpucycles.c create mode 120000 avx2/test/cpucycles.h create mode 120000 avx2/test/speed_print.c create mode 120000 avx2/test/speed_print.h create mode 120000 avx2/test/test_dilithium.c create mode 120000 avx2/test/test_mul.c create mode 120000 avx2/test/test_speed.c create mode 100644 avx2/test/test_vectors.c create mode 100644 ref/.gitignore create mode 100644 ref/Makefile create mode 100644 ref/api.h create mode 100644 ref/config.h create mode 100644 ref/fips202.c create mode 100644 ref/fips202.h create mode 100644 ref/nistkat/.gitignore create mode 100644 ref/nistkat/PQCgenKAT_sign.c create mode 100644 ref/nistkat/rng.c create mode 100644 ref/nistkat/rng.h create mode 100644 ref/ntt.c create mode 100644 ref/ntt.h create mode 100644 ref/packing.c create mode 100644 ref/packing.h create mode 100644 ref/params.h create mode 100644 ref/poly.c create mode 100644 ref/poly.h create mode 100644 ref/polyvec.c create mode 100644 ref/polyvec.h create mode 100644 ref/precomp.gp create mode 100644 ref/randombytes.c create mode 100644 ref/randombytes.h create mode 100644 ref/reduce.c create mode 100644 ref/reduce.h create mode 100644 ref/rounding.c create mode 100644 ref/rounding.h create mode 100644 ref/sign.c create mode 100644 ref/sign.h create mode 100644 ref/symmetric-shake.c create mode 100644 ref/symmetric.h create mode 100644 ref/test/.gitignore create mode 100644 ref/test/cpucycles.c create mode 100644 ref/test/cpucycles.h create mode 100644 ref/test/speed_print.c create mode 100644 ref/test/speed_print.h create mode 100644 ref/test/test_dilithium.c create mode 100644 ref/test/test_mul.c create mode 100644 ref/test/test_speed.c create mode 100644 ref/test/test_vectors.c create mode 100755 runlcov.sh create mode 100755 runtests.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17ace0a --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +PQCsignKAT_Dilithium2.req +PQCsignKAT_Dilithium2.rsp +PQCsignKAT_Dilithium3.req +PQCsignKAT_Dilithium3.rsp +PQCsignKAT_Dilithium5.req +PQCsignKAT_Dilithium5.rsp +tvecs2 +tvecs3 +tvecs5 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d389f46 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,33 @@ +language: c +os: linux +dist: bionic +compiler: + - gcc + - clang +arch: + - amd64 + - arm64 + - ppc64le + - s390x +script: ./runtests.sh + +jobs: + include: + - os: osx + osx_image: xcode11.6 + compiler: clang + env: + - CFLAGS="-I/usr/local/opt/openssl@1.1/include/" + - NISTFLAGS="-I/usr/local/opt/openssl@1.1/include/" + - LDFLAGS="-L/usr/local/opt/openssl@1.1/lib/" + + - stage: coverage + os: linux + compiler: gcc + before_install: + - sudo apt-get update + - sudo apt-get install -y lcov + - gem install coveralls-lcov + script: ./runlcov.sh + after_success: + - coveralls-lcov ref/dilithium.lcov diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 0000000..251f92c --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,7 @@ +Léo Ducas, +Eike Kiltz, +Tancrède Lepoint, +Vadim Lyubashevsky, +Gregor Seiler, +Peter Schwabe, +Damien Stehlé diff --git a/Common_META.yml b/Common_META.yml new file mode 100644 index 0000000..2efae86 --- /dev/null +++ b/Common_META.yml @@ -0,0 +1,15 @@ +commons: + - name: common_ref + folder_name: ref + sources: fips202.c fips202.h + - name: common_avx2 + folder_name: avx2 + sources: f1600x4.S fips202.c fips202.h fips202x4.c fips202x4.h + supported_platforms: + - architecture: x86_64 + operating_systems: + - Darwin + - Linux + required_flags: + - avx2 + - popcnt diff --git a/Dilithium2_META.yml b/Dilithium2_META.yml new file mode 100644 index 0000000..122b3ca --- /dev/null +++ b/Dilithium2_META.yml @@ -0,0 +1,44 @@ +name: Dilithium2 +type: signature +claimed-nist-level: 2 +length-public-key: 1312 +length-secret-key: 2560 +length-signature: 2420 +nistkat-sha256: 9a196e7fb32fbc93757dc2d8dc1924460eab66303c0c08aeb8b798fb8d8f8cf3 +testvectors-sha256: 5f0d135c0f7fd43f3fb9727265fcd6ec3651eb8c67c04ea5f3d8dfa1d99740d2 +principal-submitters: + - Vadim Lyubashevsky +auxiliary-submitters: + - Shi Bai + - Léo Ducas + - Eike Kiltz + - Tancrède Lepoint + - Peter Schwabe + - Gregor Seiler + - Damien Stehlé +implementations: + - name: ref + version: https://github.com/pq-crystals/dilithium/tree/master + folder_name: ref + compile_opts: -DDILITHIUM_MODE=2 -DDILITHIUM_RANDOMIZED_SIGNING + signature_keypair: pqcrystals_dilithium2_ref_keypair + signature_signature: pqcrystals_dilithium2_ref_signature + signature_verify: pqcrystals_dilithium2_ref_verify + sources: ../LICENSE api.h config.h params.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.c ntt.h reduce.c reduce.h rounding.c rounding.h symmetric.h fips202.h symmetric-shake.c + common_dep: common_ref + - name: avx2 + version: https://github.com/pq-crystals/dilithium/tree/master + compile_opts: -DDILITHIUM_MODE=2 -DDILITHIUM_RANDOMIZED_SIGNING + signature_keypair: pqcrystals_dilithium2_avx2_keypair + signature_signature: pqcrystals_dilithium2_avx2_signature + signature_verify: pqcrystals_dilithium2_avx2_verify + sources: ../LICENSE api.h config.h params.h align.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.S invntt.S pointwise.S ntt.h shuffle.S shuffle.inc consts.c consts.h rejsample.c rejsample.h rounding.c rounding.h symmetric.h fips202.h fips202x4.h symmetric-shake.c + common_dep: common_avx2 + supported_platforms: + - architecture: x86_64 + operating_systems: + - Darwin + - Linux + required_flags: + - avx2 + - popcnt diff --git a/Dilithium3_META.yml b/Dilithium3_META.yml new file mode 100644 index 0000000..b108b4f --- /dev/null +++ b/Dilithium3_META.yml @@ -0,0 +1,44 @@ +name: Dilithium3 +type: signature +claimed-nist-level: 3 +length-public-key: 1952 +length-secret-key: 4032 +length-signature: 3309 +nistkat-sha256: 7cb96242eac9907a55b5c84c202f0ebd552419c50b2e986dc2e28f07ecebf072 +testvectors-sha256: 14bf84918ee90e7afbd580191d3eb890d4557e0900b1145e39a8399ef7dd3fba +principal-submitters: + - Vadim Lyubashevsky +auxiliary-submitters: + - Shi Bai + - Léo Ducas + - Eike Kiltz + - Tancrède Lepoint + - Peter Schwabe + - Gregor Seiler + - Damien Stehlé +implementations: + - name: ref + version: https://github.com/pq-crystals/dilithium/tree/master + folder_name: ref + compile_opts: -DDILITHIUM_MODE=3 -DDILITHIUM_RANDOMIZED_SIGNING + signature_keypair: pqcrystals_dilithium3_ref_keypair + signature_signature: pqcrystals_dilithium3_ref_signature + signature_verify: pqcrystals_dilithium3_ref_verify + sources: ../LICENSE api.h config.h params.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.c ntt.h reduce.c reduce.h rounding.c rounding.h symmetric.h fips202.h symmetric-shake.c + common_dep: common_ref + - name: avx2 + version: https://github.com/pq-crystals/dilithium/tree/master + compile_opts: -DDILITHIUM_MODE=3 -DDILITHIUM_RANDOMIZED_SIGNING + signature_keypair: pqcrystals_dilithium3_avx2_keypair + signature_signature: pqcrystals_dilithium3_avx2_signature + signature_verify: pqcrystals_dilithium3_avx2_verify + sources: ../LICENSE api.h config.h params.h align.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.S invntt.S pointwise.S ntt.h shuffle.S shuffle.inc consts.c consts.h rejsample.c rejsample.h rounding.c rounding.h symmetric.h fips202.h fips202x4.h symmetric-shake.c + common_dep: common_avx2 + supported_platforms: + - architecture: x86_64 + operating_systems: + - Darwin + - Linux + required_flags: + - avx2 + - popcnt diff --git a/Dilithium5_META.yml b/Dilithium5_META.yml new file mode 100644 index 0000000..5163526 --- /dev/null +++ b/Dilithium5_META.yml @@ -0,0 +1,44 @@ +name: Dilithium5 +type: signature +claimed-nist-level: 5 +length-public-key: 2592 +length-secret-key: 4896 +length-signature: 4627 +nistkat-sha256: 4537905d2aabcf302fab2f242baed293459ecda7c230e6a67063b02c7e2840ed +testvectors-sha256: 759a3ba35210c7e27ff90a7ce5e399295533b82ef125e6ec98af158e00268e44 +principal-submitters: + - Vadim Lyubashevsky +auxiliary-submitters: + - Shi Bai + - Léo Ducas + - Eike Kiltz + - Tancrède Lepoint + - Peter Schwabe + - Gregor Seiler + - Damien Stehlé +implementations: + - name: ref + version: https://github.com/pq-crystals/dilithium/tree/master + folder_name: ref + compile_opts: -DDILITHIUM_MODE=5 -DDILITHIUM_RANDOMIZED_SIGNING + signature_keypair: pqcrystals_dilithium5_ref_keypair + signature_signature: pqcrystals_dilithium5_ref_signature + signature_verify: pqcrystals_dilithium5_ref_verify + sources: ../LICENSE api.h config.h params.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.c ntt.h reduce.c reduce.h rounding.c rounding.h symmetric.h fips202.h symmetric-shake.c + common_dep: common_ref + - name: avx2 + version: https://github.com/pq-crystals/dilithium/tree/master + compile_opts: -DDILITHIUM_MODE=5 -DDILITHIUM_RANDOMIZED_SIGNING + signature_keypair: pqcrystals_dilithium5_avx2_keypair + signature_signature: pqcrystals_dilithium5_avx2_signature + signature_verify: pqcrystals_dilithium5_avx2_verify + sources: ../LICENSE api.h config.h params.h align.h sign.c sign.h packing.c packing.h polyvec.c polyvec.h poly.c poly.h ntt.S invntt.S pointwise.S ntt.h shuffle.S shuffle.inc consts.c consts.h rejsample.c rejsample.h rounding.c rounding.h symmetric.h fips202.h fips202x4.h symmetric-shake.c + common_dep: common_avx2 + supported_platforms: + - architecture: x86_64 + operating_systems: + - Darwin + - Linux + required_flags: + - avx2 + - popcnt diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c086379 --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Public Domain (https://creativecommons.org/share-your-work/public-domain/cc0/); +or Apache 2.0 License (https://www.apache.org/licenses/LICENSE-2.0.html) or GPL 2.0 License (http://www.gnu.org/licenses/gpl-2.0.html). + +For Keccak and the random number generator +we are using public-domain code from sources +and by authors listed in comments on top of +the respective files. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9204fa6 --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# Dilithium + +[![Build Status](https://travis-ci.org/pq-crystals/dilithium.svg?branch=master)](https://travis-ci.org/pq-crystals/dilithium) [![Coverage Status](https://coveralls.io/repos/github/pq-crystals/dilithium/badge.svg?branch=master)](https://coveralls.io/github/pq-crystals/dilithium?branch=master) + +This repository contains the official reference implementation of the [Dilithium](https://www.pq-crystals.org/dilithium/) signature scheme, and an optimized implementation for x86 CPUs supporting the AVX2 instruction set. Dilithium is standardized as [FIPS 204](https://csrc.nist.gov/pubs/fips/204/final). + +## Build instructions + +The implementations contain several test and benchmarking programs and a Makefile to facilitate compilation. + +### Prerequisites + +Some of the test programs require [OpenSSL](https://openssl.org). If the OpenSSL header files and/or shared libraries do not lie in one of the standard locations on your system, it is necessary to specify their location via compiler and linker flags in the environment variables `CFLAGS`, `NISTFLAGS`, and `LDFLAGS`. + +For example, on macOS you can install OpenSSL via [Homebrew](https://brew.sh) by running +```sh +brew install openssl +``` +Then, run +```sh +export CFLAGS="-I/opt/homebrew/opt/openssl@1.1/include" +export NISTFLAGS="-I/opt/homebrew/opt/openssl@1.1/include" +export LDFLAGS="-L/opt/homebrew/opt/openssl@1.1/lib" +``` +before compilation to add the OpenSSL header and library locations to the respective search paths. + +### Test programs + +To compile the test programs on Linux or macOS, go to the `ref/` or `avx2/` directory and run +```sh +make +``` +This produces the executables +```sh +test/test_dilithium$ALG +test/test_vectors$ALG +``` +where `$ALG` ranges over the parameter sets 2, 3, and 5. + +* `test_dilithium$ALG` tests 10000 times to generate keys, sign a random message of 59 bytes and verify the produced signature. Also, the program will try to verify wrong signatures where a single random byte of a valid signature was randomly distorted. The program will abort with an error message and return -1 if there was an error. Otherwise it will output the key and signature sizes and return 0. +* `test_vectors$ALG` performs further tests of internal functions and prints deterministically generated test vectors for several intermediate values that occur in the Dilithium algorithms. Namely, a 48 byte seed, the matrix A corresponding to the first 32 bytes of seed, a short secret vector s corresponding to the first 32 bytes of seed and nonce 0, a masking vector y corresponding to the seed and nonce 0, the high bits w1 and the low bits w0 of the vector w = Ay, the power-of-two rounding t1 of w and the corresponding low part t0, and the challenge c for the seed and w1. This program is meant to help to ensure compatibility of independent implementations. + +### Benchmarking programs + +For benchmarking the implementations, we provide speed test programs for x86 CPUs that use the Time Step Counter (TSC) or the actual cycle counter provided by the Performance Measurement Counters (PMC) to measure performance. To compile the programs run +```sh +make speed +``` +This produces the executables +```sh +test/test_speed$ALG +``` +for all parameter sets `$ALG` as above. The programs report the median and average cycle counts of 10000 executions of various internal functions and the API functions for key generation, signing and verification. By default the Time Step Counter is used. If instead you want to obtain the actual cycle counts from the Performance Measurement Counters export `CFLAGS="-DUSE_RDPMC"` before compilation. + +Please note that the reference implementation in `ref/` is not optimized for any platform, and, since it prioritises clean code, is significantly slower than a trivially optimized but still platform-independent implementation. Hence benchmarking the reference code does not provide representative results. + +Our Dilithium implementations are contained in the [SUPERCOP](https://bench.cr.yp.to) benchmarking framework. See [here](http://bench.cr.yp.to/results-sign.html#amd64-kizomba) for current cycle counts on an Intel KabyLake CPU. + +## Randomized signing + +By default our code implements Dilithium's hedged signing mode. To change this to the deterministic signing mode, undefine the `DILITHIUM_RANDOMIZED_SIGNING` preprocessor macro at compilation by either commenting the line +```sh +#define DILITHIUM_RANDOMIZED_SIGNING +``` +in config.h, or adding `-UDILITHIUM_RANDOMIZED_SIGNING` to the compiler flags in the environment variable `CFLAGS`. + +## Shared libraries + +All implementations can be compiled into shared libraries by running +```sh +make shared +``` +For example in the directory `ref/` of the reference implementation, this produces the libraries +```sh +libpqcrystals_dilithium$ALG_ref.so +``` +for all parameter sets `$ALG`, and the required symmetric crypto library +``` +libpqcrystals_fips202_ref.so +``` +All global symbols in the libraries lie in the namespaces `pqcrystals_dilithium$ALG_ref` and `libpqcrystals_fips202_ref`. Hence it is possible to link a program against all libraries simultaneously and obtain access to all implementations for all parameter sets. The corresponding API header file is `ref/api.h`, which contains prototypes for all API functions and preprocessor defines for the key and signature lengths. diff --git a/SHA256SUMS b/SHA256SUMS new file mode 100644 index 0000000..3e5914f --- /dev/null +++ b/SHA256SUMS @@ -0,0 +1,3 @@ +5f0d135c0f7fd43f3fb9727265fcd6ec3651eb8c67c04ea5f3d8dfa1d99740d2 tvecs2 +14bf84918ee90e7afbd580191d3eb890d4557e0900b1145e39a8399ef7dd3fba tvecs3 +759a3ba35210c7e27ff90a7ce5e399295533b82ef125e6ec98af158e00268e44 tvecs5 diff --git a/avx2/.gitignore b/avx2/.gitignore new file mode 100644 index 0000000..cc78368 --- /dev/null +++ b/avx2/.gitignore @@ -0,0 +1,2 @@ +*.so +*.o diff --git a/avx2/Makefile b/avx2/Makefile new file mode 100644 index 0000000..f85cfc0 --- /dev/null +++ b/avx2/Makefile @@ -0,0 +1,118 @@ +CC ?= /usr/bin/cc +CFLAGS += -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wredundant-decls \ + -Wshadow -Wpointer-arith -mavx2 -mpopcnt \ + -march=native -mtune=native -O3 +NISTFLAGS += -Wno-unused-result -mavx2 -mpopcnt \ + -march=native -mtune=native -O3 +SOURCES = sign.c packing.c polyvec.c poly.c ntt.S invntt.S pointwise.S \ + shuffle.S consts.c rejsample.c rounding.c +HEADERS = align.h config.h params.h api.h sign.h packing.h polyvec.h poly.h ntt.h \ + consts.h shuffle.inc rejsample.h rounding.h symmetric.h randombytes.h +KECCAK_SOURCES = $(SOURCES) fips202.c fips202x4.c f1600x4.S symmetric-shake.c +KECCAK_HEADERS = $(HEADERS) fips202.h fips202x4.h + +.PHONY: all shared clean + +all: \ + test/test_dilithium2 \ + test/test_dilithium3 \ + test/test_dilithium5 \ + test/test_vectors2 \ + test/test_vectors3 \ + test/test_vectors5 \ + speed + +speed: \ + test/test_speed2 \ + test/test_speed3 \ + test/test_speed5 \ + +shared: \ + libpqcrystals_dilithium2_avx2.so \ + libpqcrystals_dilithium3_avx2.so \ + libpqcrystals_dilithium5_avx2.so \ + libpqcrystals_fips202_avx2.so \ + libpqcrystals_fips202x4_avx2.so \ + +libpqcrystals_fips202_avx2.so: fips202.c fips202.h + $(CC) -shared -fPIC $(CFLAGS) -o $@ $< + +libpqcrystals_fips202x4_avx2.so: fips202x4.c fips202x4.h f1600x4.S + $(CC) -shared -fPIC $(CFLAGS) -o $@ $< f1600x4.S + +libpqcrystals_dilithium2_avx2.so: $(SOURCES) $(HEADERS) symmetric-shake.c + $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=2 \ + -o $@ $(SOURCES) symmetric-shake.c + +libpqcrystals_dilithium3_avx2.so: $(SOURCES) $(HEADERS) symmetric-shake.c + $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=3 \ + -o $@ $(SOURCES) symmetric-shake.c + +libpqcrystals_dilithium5_avx2.so: $(SOURCES) $(HEADERS) symmetric-shake.c + $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=5 \ + -o $@ $(SOURCES) symmetric-shake.c + +test/test_dilithium2: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ + -o $@ $< randombytes.c $(KECCAK_SOURCES) + +test/test_dilithium3: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ + -o $@ $< randombytes.c $(KECCAK_SOURCES) + +test/test_dilithium5: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ + -o $@ $< randombytes.c $(KECCAK_SOURCES) + +test/test_vectors2: test/test_vectors.c $(KECCAK_SOURCES) $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ + -o $@ $< $(KECCAK_SOURCES) + +test/test_vectors3: test/test_vectors.c $(KECCAK_SOURCES) $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ + -o $@ $< $(KECCAK_SOURCES) + +test/test_vectors5: test/test_vectors.c $(KECCAK_SOURCES) $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ + -o $@ $< $(KECCAK_SOURCES) + +test/test_speed2: test/test_speed.c test/speed_print.c test/speed_print.h \ + test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ + -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ + $(KECCAK_SOURCES) + +test/test_speed3: test/test_speed.c test/speed_print.c test/speed_print.h \ + test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ + -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ + $(KECCAK_SOURCES) + +test/test_speed5: test/test_speed.c test/speed_print.c test/speed_print.h \ + test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ + -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ + $(KECCAK_SOURCES) + +test/test_mul: test/test_mul.c randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -UDBENCH -o $@ $< randombytes.c $(KECCAK_SOURCES) + +clean: + rm -f *.o *.a *.so + rm -f test/test_dilithium2 + rm -f test/test_dilithium3 + rm -f test/test_dilithium5 + rm -f test/test_vectors2 + rm -f test/test_vectors3 + rm -f test/test_vectors5 + rm -f test/test_speed2 + rm -f test/test_speed3 + rm -f test/test_speed5 + rm -f test/test_mul diff --git a/avx2/align.h b/avx2/align.h new file mode 100644 index 0000000..33fac1d --- /dev/null +++ b/avx2/align.h @@ -0,0 +1,19 @@ +#ifndef ALIGN_H +#define ALIGN_H + +#include +#include + +#define ALIGNED_UINT8(N) \ + union { \ + uint8_t coeffs[N]; \ + __m256i vec[(N+31)/32]; \ + } + +#define ALIGNED_INT32(N) \ + union { \ + int32_t coeffs[N]; \ + __m256i vec[(N+7)/8]; \ + } + +#endif diff --git a/avx2/api.h b/avx2/api.h new file mode 100644 index 0000000..36ec622 --- /dev/null +++ b/avx2/api.h @@ -0,0 +1,100 @@ +#ifndef API_H +#define API_H + +#include +#include + +#define pqcrystals_dilithium2_PUBLICKEYBYTES 1312 +#define pqcrystals_dilithium2_SECRETKEYBYTES 2560 +#define pqcrystals_dilithium2_BYTES 2420 + +#define pqcrystals_dilithium2_avx2_PUBLICKEYBYTES pqcrystals_dilithium2_PUBLICKEYBYTES +#define pqcrystals_dilithium2_avx2_SECRETKEYBYTES pqcrystals_dilithium2_SECRETKEYBYTES +#define pqcrystals_dilithium2_avx2_BYTES pqcrystals_dilithium2_BYTES + +int pqcrystals_dilithium2_avx2_keypair(uint8_t *pk, uint8_t *sk); + +int pqcrystals_dilithium2_avx2_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium2_avx2(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium2_avx2_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +int pqcrystals_dilithium2_avx2_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + + +#define pqcrystals_dilithium3_PUBLICKEYBYTES 1952 +#define pqcrystals_dilithium3_SECRETKEYBYTES 4032 +#define pqcrystals_dilithium3_BYTES 3309 + +#define pqcrystals_dilithium3_avx2_PUBLICKEYBYTES pqcrystals_dilithium3_PUBLICKEYBYTES +#define pqcrystals_dilithium3_avx2_SECRETKEYBYTES pqcrystals_dilithium3_SECRETKEYBYTES +#define pqcrystals_dilithium3_avx2_BYTES pqcrystals_dilithium3_BYTES + +int pqcrystals_dilithium3_avx2_keypair(uint8_t *pk, uint8_t *sk); + +int pqcrystals_dilithium3_avx2_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium3_avx2(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium3_avx2_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +int pqcrystals_dilithium3_avx2_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + + +#define pqcrystals_dilithium5_PUBLICKEYBYTES 2592 +#define pqcrystals_dilithium5_SECRETKEYBYTES 4896 +#define pqcrystals_dilithium5_BYTES 4627 + +#define pqcrystals_dilithium5_avx2_PUBLICKEYBYTES pqcrystals_dilithium5_PUBLICKEYBYTES +#define pqcrystals_dilithium5_avx2_SECRETKEYBYTES pqcrystals_dilithium5_SECRETKEYBYTES +#define pqcrystals_dilithium5_avx2_BYTES pqcrystals_dilithium5_BYTES + +int pqcrystals_dilithium5_avx2_keypair(uint8_t *pk, uint8_t *sk); + +int pqcrystals_dilithium5_avx2_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium5_avx2(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium5_avx2_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +int pqcrystals_dilithium5_avx2_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + + +#endif diff --git a/avx2/config.h b/avx2/config.h new file mode 100644 index 0000000..a9facc0 --- /dev/null +++ b/avx2/config.h @@ -0,0 +1,27 @@ +#ifndef CONFIG_H +#define CONFIG_H + +//#define DILITHIUM_MODE 2 +#define DILITHIUM_RANDOMIZED_SIGNING +//#define USE_RDPMC +//#define DBENCH + +#ifndef DILITHIUM_MODE +#define DILITHIUM_MODE 2 +#endif + +#if DILITHIUM_MODE == 2 +#define CRYPTO_ALGNAME "Dilithium2" +#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium2_avx2 +#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium2_avx2_##s +#elif DILITHIUM_MODE == 3 +#define CRYPTO_ALGNAME "Dilithium3" +#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium3_avx2 +#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium3_avx2_##s +#elif DILITHIUM_MODE == 5 +#define CRYPTO_ALGNAME "Dilithium5" +#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium5_avx2 +#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium5_avx2_##s +#endif + +#endif diff --git a/avx2/consts.c b/avx2/consts.c new file mode 100644 index 0000000..414d99e --- /dev/null +++ b/avx2/consts.c @@ -0,0 +1,100 @@ +#include +#include "params.h" +#include "consts.h" + +#define QINV 58728449 // q^(-1) mod 2^32 +#define MONT -4186625 // 2^32 mod q +#define DIV 41978 // mont^2/256 +#define DIV_QINV -8395782 + +const qdata_t qdata = {{ +#define _8XQ 0 + Q, Q, Q, Q, Q, Q, Q, Q, + +#define _8XQINV 8 + QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, + +#define _8XDIV_QINV 16 + DIV_QINV, DIV_QINV, DIV_QINV, DIV_QINV, DIV_QINV, DIV_QINV, DIV_QINV, DIV_QINV, + +#define _8XDIV 24 + DIV, DIV, DIV, DIV, DIV, DIV, DIV, DIV, + +#define _ZETAS_QINV 32 + -151046689, 1830765815, -1929875198, -1927777021, 1640767044, 1477910808, 1612161320, 1640734244, + 308362795, 308362795, 308362795, 308362795, -1815525077, -1815525077, -1815525077, -1815525077, + -1374673747, -1374673747, -1374673747, -1374673747, -1091570561, -1091570561, -1091570561, -1091570561, + -1929495947, -1929495947, -1929495947, -1929495947, 515185417, 515185417, 515185417, 515185417, + -285697463, -285697463, -285697463, -285697463, 625853735, 625853735, 625853735, 625853735, + 1727305304, 1727305304, 2082316400, 2082316400, -1364982364, -1364982364, 858240904, 858240904, + 1806278032, 1806278032, 222489248, 222489248, -346752664, -346752664, 684667771, 684667771, + 1654287830, 1654287830, -878576921, -878576921, -1257667337, -1257667337, -748618600, -748618600, + 329347125, 329347125, 1837364258, 1837364258, -1443016191, -1443016191, -1170414139, -1170414139, + -1846138265, -1631226336, -1404529459, 1838055109, 1594295555, -1076973524, -1898723372, -594436433, + -202001019, -475984260, -561427818, 1797021249, -1061813248, 2059733581, -1661512036, -1104976547, + -1750224323, -901666090, 418987550, 1831915353, -1925356481, 992097815, 879957084, 2024403852, + 1484874664, -1636082790, -285388938, -1983539117, -1495136972, -950076368, -1714807468, -952438995, + -1574918427, 1350681039, -2143979939, 1599739335, -1285853323, -993005454, -1440787840, 568627424, + -783134478, -588790216, 289871779, -1262003603, 2135294594, -1018755525, -889861155, 1665705315, + 1321868265, 1225434135, -1784632064, 666258756, 675310538, -1555941048, -1999506068, -1499481951, + -695180180, -1375177022, 1777179795, 334803717, -178766299, -518252220, 1957047970, 1146323031, + -654783359, -1974159335, 1651689966, 140455867, -1039411342, 1955560694, 1529189038, -2131021878, + -247357819, 1518161567, -86965173, 1708872713, 1787797779, 1638590967, -120646188, -1669960606, + -916321552, 1155548552, 2143745726, 1210558298, -1261461890, -318346816, 628664287, -1729304568, + 1422575624, 1424130038, -1185330464, 235321234, 168022240, 1206536194, 985155484, -894060583, + -898413, -1363460238, -605900043, 2027833504, 14253662, 1014493059, 863641633, 1819892093, + 2124962073, -1223601433, -1920467227, -1637785316, -1536588520, 694382729, 235104446, -1045062172, + 831969619, -300448763, 756955444, -260312805, 1554794072, 1339088280, -2040058690, -853476187, + -2047270596, -1723816713, -1591599803, -440824168, 1119856484, 1544891539, 155290192, -973777462, + 991903578, 912367099, -44694137, 1176904444, -421552614, -818371958, 1747917558, -325927722, + 908452108, 1851023419, -1176751719, -1354528380, -72690498, -314284737, 985022747, 963438279, + -1078959975, 604552167, -1021949428, 608791570, 173440395, -2126092136, -1316619236, -1039370342, + 6087993, -110126092, 565464272, -1758099917, -1600929361, 879867909, -1809756372, 400711272, + 1363007700, 30313375, -326425360, 1683520342, -517299994, 2027935492, -1372618620, 128353682, + -1123881663, 137583815, -635454918, -642772911, 45766801, 671509323, -2070602178, 419615363, + 1216882040, -270590488, -1276805128, 371462360, -1357098057, -384158533, 827959816, -596344473, + 702390549, -279505433, -260424530, -71875110, -1208667171, -1499603926, 2036925262, -540420426, + 746144248, -1420958686, 2032221021, 1904936414, 1257750362, 1926727420, 1931587462, 1258381762, + 885133339, 1629985060, 1967222129, 6363718, -1287922800, 1136965286, 1779436847, 1116720494, + 1042326957, 1405999311, 713994583, 940195359, -1542497137, 2061661095, -883155599, 1726753853, + -1547952704, 394851342, 283780712, 776003547, 1123958025, 201262505, 1934038751, 374860238, + +#define _ZETAS 328 + -3975713, 25847, -2608894, -518909, 237124, -777960, -876248, 466468, + 1826347, 1826347, 1826347, 1826347, 2353451, 2353451, 2353451, 2353451, + -359251, -359251, -359251, -359251, -2091905, -2091905, -2091905, -2091905, + 3119733, 3119733, 3119733, 3119733, -2884855, -2884855, -2884855, -2884855, + 3111497, 3111497, 3111497, 3111497, 2680103, 2680103, 2680103, 2680103, + 2725464, 2725464, 1024112, 1024112, -1079900, -1079900, 3585928, 3585928, + -549488, -549488, -1119584, -1119584, 2619752, 2619752, -2108549, -2108549, + -2118186, -2118186, -3859737, -3859737, -1399561, -1399561, -3277672, -3277672, + 1757237, 1757237, -19422, -19422, 4010497, 4010497, 280005, 280005, + 2706023, 95776, 3077325, 3530437, -1661693, -3592148, -2537516, 3915439, + -3861115, -3043716, 3574422, -2867647, 3539968, -300467, 2348700, -539299, + -1699267, -1643818, 3505694, -3821735, 3507263, -2140649, -1600420, 3699596, + 811944, 531354, 954230, 3881043, 3900724, -2556880, 2071892, -2797779, + -3930395, -3677745, -1452451, 2176455, -1257611, -4083598, -3190144, -3632928, + 3412210, 2147896, -2967645, -411027, -671102, -22981, -381987, 1852771, + -3343383, 508951, 44288, 904516, -3724342, 1653064, 2389356, 759969, + 189548, 3159746, -2409325, 1315589, 1285669, -812732, -3019102, -3628969, + -1528703, -3041255, 3475950, -1585221, 1939314, -1000202, -3157330, 126922, + -983419, 2715295, -3693493, -2477047, -1228525, -1308169, 1349076, -1430430, + 264944, 3097992, -1100098, 3958618, -8578, -3249728, -210977, -1316856, + -3553272, -1851402, -177440, 1341330, -1584928, -1439742, -3881060, 3839961, + 2091667, -3342478, 266997, -3520352, 900702, 495491, -655327, -3556995, + 342297, 3437287, 2842341, 4055324, -3767016, -2994039, -1333058, -451100, + -1279661, 1500165, -542412, -2584293, -2013608, 1957272, -3183426, 810149, + -3038916, 2213111, -426683, -1667432, -2939036, 183443, -554416, 3937738, + 3407706, 2244091, 2434439, -3759364, 1859098, -1613174, -3122442, -525098, + 286988, -3342277, 2691481, 1247620, 1250494, 1869119, 1237275, 1312455, + 1917081, 777191, -2831860, -3724270, 2432395, 3369112, 162844, 1652634, + 3523897, -975884, 1723600, -1104333, -2235985, -976891, 3919660, 1400424, + 2316500, -2446433, -1235728, -1197226, 909542, -43260, 2031748, -768622, + -2437823, 1735879, -2590150, 2486353, 2635921, 1903435, -3318210, 3306115, + -2546312, 2235880, -1671176, 594136, 2454455, 185531, 1616392, -3694233, + 3866901, 1717735, -1803090, -260646, -420899, 1612842, -48306, -846154, + 3817976, -3562462, 3513181, -3193378, 819034, -522500, 3207046, -3595838, + 4108315, 203044, 1265009, 1595974, -3548272, -1050970, -1430225, -1962642, + -1374803, 3406031, -1846953, -3776993, -164721, -1207385, 3014001, -1799107, + 269760, 472078, 1910376, -3833893, -2286327, -3545687, -1362209, 1976782, +}}; diff --git a/avx2/consts.h b/avx2/consts.h new file mode 100644 index 0000000..930d2f0 --- /dev/null +++ b/avx2/consts.h @@ -0,0 +1,38 @@ +#ifndef CONSTS_H +#define CONSTS_H + +#include "params.h" + +#define _8XQ 0 +#define _8XQINV 8 +#define _8XDIV_QINV 16 +#define _8XDIV 24 +#define _ZETAS_QINV 32 +#define _ZETAS 328 + +/* The C ABI on MacOS exports all symbols with a leading + * underscore. This means that any symbols we refer to from + * C files (functions) can't be found, and all symbols we + * refer to from ASM also can't be found. + * + * This define helps us get around this + */ +#if defined(__WIN32__) || defined(__APPLE__) +#define decorate(s) _##s +#define _cdecl(s) decorate(s) +#define cdecl(s) _cdecl(DILITHIUM_NAMESPACE(##s)) +#else +#define cdecl(s) DILITHIUM_NAMESPACE(##s) +#endif + +#ifndef __ASSEMBLER__ + +#include "align.h" + +typedef ALIGNED_INT32(624) qdata_t; + +#define qdata DILITHIUM_NAMESPACE(qdata) +extern const qdata_t qdata; + +#endif +#endif diff --git a/avx2/f1600x4.S b/avx2/f1600x4.S new file mode 100644 index 0000000..5455129 --- /dev/null +++ b/avx2/f1600x4.S @@ -0,0 +1,909 @@ +/* Taken from Bas Westerbaan's new 4-way SHAKE implementation + * for Sphincs+ (https://github.com/sphincs/sphincsplus/pull/14/), + * but uses vpshufb for byte-granular rotations as in the Keccak Code Package. */ + +#include "fips202x4.h" + +.data +.p2align 5 +rho8: +.byte 7,0,1,2,3,4,5,6,15,8,9,10,11,12,13,14,7,0,1,2,3,4,5,6,15,8,9,10,11,12,13,14 +rho56: +.byte 1,2,3,4,5,6,7,0,9,10,11,12,13,14,15,8,1,2,3,4,5,6,7,0,9,10,11,12,13,14,15,8 + +.text +.global cdecl(f1600x4) +cdecl(f1600x4): +vmovdqa rho8(%rip), %ymm0 +movq $6, %rax +looptop: +vmovdqa 0(%rdi), %ymm8 +vmovdqa 32(%rdi), %ymm9 +vmovdqa 64(%rdi), %ymm10 +vmovdqa 96(%rdi), %ymm11 +vmovdqa 128(%rdi), %ymm12 +vpxor 160(%rdi), %ymm8, %ymm8 +vpxor 192(%rdi), %ymm9, %ymm9 +vpxor 224(%rdi), %ymm10, %ymm10 +vpxor 256(%rdi), %ymm11, %ymm11 +vpxor 288(%rdi), %ymm12, %ymm12 +vpxor 320(%rdi), %ymm8, %ymm8 +vpxor 352(%rdi), %ymm9, %ymm9 +vpxor 384(%rdi), %ymm10, %ymm10 +vpxor 416(%rdi), %ymm11, %ymm11 +vpxor 448(%rdi), %ymm12, %ymm12 +vpxor 480(%rdi), %ymm8, %ymm8 +vpxor 512(%rdi), %ymm9, %ymm9 +vpxor 544(%rdi), %ymm10, %ymm10 +vpxor 576(%rdi), %ymm11, %ymm11 +vpxor 608(%rdi), %ymm12, %ymm12 +vpxor 640(%rdi), %ymm8, %ymm8 +vpxor 672(%rdi), %ymm9, %ymm9 +vpxor 704(%rdi), %ymm10, %ymm10 +vpxor 736(%rdi), %ymm11, %ymm11 +vpxor 768(%rdi), %ymm12, %ymm12 +vpsllq $1, %ymm9, %ymm13 +vpsllq $1, %ymm10, %ymm14 +vpsllq $1, %ymm11, %ymm15 +vpsllq $1, %ymm12, %ymm7 +vpsllq $1, %ymm8, %ymm6 +vpsrlq $63, %ymm9, %ymm5 +vpsrlq $63, %ymm10, %ymm4 +vpsrlq $63, %ymm11, %ymm3 +vpsrlq $63, %ymm12, %ymm2 +vpsrlq $63, %ymm8, %ymm1 +vpor %ymm13, %ymm5, %ymm5 +vpor %ymm14, %ymm4, %ymm4 +vpor %ymm15, %ymm3, %ymm3 +vpor %ymm7, %ymm2, %ymm2 +vpor %ymm6, %ymm1, %ymm1 +vpxor %ymm5, %ymm12, %ymm5 +vpxor %ymm4, %ymm8, %ymm4 +vpxor %ymm3, %ymm9, %ymm3 +vpxor %ymm2, %ymm10, %ymm2 +vpxor %ymm1, %ymm11, %ymm1 +vpxor 0(%rdi), %ymm5, %ymm8 +vpxor 192(%rdi), %ymm4, %ymm9 +vpxor 384(%rdi), %ymm3, %ymm10 +vpxor 576(%rdi), %ymm2, %ymm11 +vpxor 768(%rdi), %ymm1, %ymm12 +vpsllq $44, %ymm9, %ymm14 +vpsllq $43, %ymm10, %ymm15 +vpsllq $21, %ymm11, %ymm7 +vpsllq $14, %ymm12, %ymm6 +vpsrlq $20, %ymm9, %ymm9 +vpsrlq $21, %ymm10, %ymm10 +vpsrlq $43, %ymm11, %ymm11 +vpsrlq $50, %ymm12, %ymm12 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vpbroadcastq 0(%rsi), %ymm8 +vpxor %ymm8, %ymm13, %ymm13 +vmovdqa %ymm13, 0(%rdi) +vmovdqa %ymm14, 192(%rdi) +vmovdqa %ymm15, 384(%rdi) +vmovdqa %ymm7, 576(%rdi) +vmovdqa %ymm6, 768(%rdi) +vpxor 96(%rdi), %ymm2, %ymm8 +vpxor 288(%rdi), %ymm1, %ymm9 +vpxor 320(%rdi), %ymm5, %ymm10 +vpxor 512(%rdi), %ymm4, %ymm11 +vpxor 704(%rdi), %ymm3, %ymm12 +vpsllq $28, %ymm8, %ymm13 +vpsllq $20, %ymm9, %ymm14 +vpsllq $3, %ymm10, %ymm15 +vpsllq $45, %ymm11, %ymm7 +vpsllq $61, %ymm12, %ymm6 +vpsrlq $36, %ymm8, %ymm8 +vpsrlq $44, %ymm9, %ymm9 +vpsrlq $61, %ymm10, %ymm10 +vpsrlq $19, %ymm11, %ymm11 +vpsrlq $3, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 320(%rdi) +vmovdqa %ymm14, 512(%rdi) +vmovdqa %ymm15, 704(%rdi) +vmovdqa %ymm7, 96(%rdi) +vmovdqa %ymm6, 288(%rdi) +vpxor 32(%rdi), %ymm4, %ymm8 +vpxor 224(%rdi), %ymm3, %ymm9 +vpxor 416(%rdi), %ymm2, %ymm10 +vpxor 608(%rdi), %ymm1, %ymm11 +vpxor 640(%rdi), %ymm5, %ymm12 +vpsllq $1, %ymm8, %ymm13 +vpsllq $6, %ymm9, %ymm14 +vpsllq $25, %ymm10, %ymm15 +#vpsllq $8, %ymm11, %ymm7 +vpsllq $18, %ymm12, %ymm6 +vpsrlq $63, %ymm8, %ymm8 +vpsrlq $58, %ymm9, %ymm9 +vpsrlq $39, %ymm10, %ymm10 +#vpsrlq $56, %ymm11, %ymm11 +vpsrlq $46, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +#vpor %ymm7, %ymm11, %ymm11 +vpshufb %ymm0, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 640(%rdi) +vmovdqa %ymm14, 32(%rdi) +vmovdqa %ymm15, 224(%rdi) +vmovdqa %ymm7, 416(%rdi) +vmovdqa %ymm6, 608(%rdi) +vpxor 128(%rdi), %ymm1, %ymm8 +vpxor 160(%rdi), %ymm5, %ymm9 +vpxor 352(%rdi), %ymm4, %ymm10 +vpxor 544(%rdi), %ymm3, %ymm11 +vpxor 736(%rdi), %ymm2, %ymm12 +vpsllq $27, %ymm8, %ymm13 +vpsllq $36, %ymm9, %ymm14 +vpsllq $10, %ymm10, %ymm15 +vpsllq $15, %ymm11, %ymm7 +#vpsllq $56, %ymm12, %ymm6 +vpsrlq $37, %ymm8, %ymm8 +vpsrlq $28, %ymm9, %ymm9 +vpsrlq $54, %ymm10, %ymm10 +vpsrlq $49, %ymm11, %ymm11 +#vpsrlq $8, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +#vpor %ymm6, %ymm12, %ymm12 +vpshufb rho56(%rip), %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 160(%rdi) +vmovdqa %ymm14, 352(%rdi) +vmovdqa %ymm15, 544(%rdi) +vmovdqa %ymm7, 736(%rdi) +vmovdqa %ymm6, 128(%rdi) +vpxor 64(%rdi), %ymm3, %ymm8 +vpxor 256(%rdi), %ymm2, %ymm9 +vpxor 448(%rdi), %ymm1, %ymm10 +vpxor 480(%rdi), %ymm5, %ymm11 +vpxor 672(%rdi), %ymm4, %ymm12 +vpsllq $62, %ymm8, %ymm13 +vpsllq $55, %ymm9, %ymm14 +vpsllq $39, %ymm10, %ymm15 +vpsllq $41, %ymm11, %ymm7 +vpsllq $2, %ymm12, %ymm6 +vpsrlq $2, %ymm8, %ymm8 +vpsrlq $9, %ymm9, %ymm9 +vpsrlq $25, %ymm10, %ymm10 +vpsrlq $23, %ymm11, %ymm11 +vpsrlq $62, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 480(%rdi) +vmovdqa %ymm14, 672(%rdi) +vmovdqa %ymm15, 64(%rdi) +vmovdqa %ymm7, 256(%rdi) +vmovdqa %ymm6, 448(%rdi) +vmovdqa 0(%rdi), %ymm8 +vmovdqa 32(%rdi), %ymm9 +vmovdqa 64(%rdi), %ymm10 +vmovdqa 96(%rdi), %ymm11 +vmovdqa 128(%rdi), %ymm12 +vpxor 160(%rdi), %ymm8, %ymm8 +vpxor 192(%rdi), %ymm9, %ymm9 +vpxor 224(%rdi), %ymm10, %ymm10 +vpxor 256(%rdi), %ymm11, %ymm11 +vpxor 288(%rdi), %ymm12, %ymm12 +vpxor 320(%rdi), %ymm8, %ymm8 +vpxor 352(%rdi), %ymm9, %ymm9 +vpxor 384(%rdi), %ymm10, %ymm10 +vpxor 416(%rdi), %ymm11, %ymm11 +vpxor 448(%rdi), %ymm12, %ymm12 +vpxor 480(%rdi), %ymm8, %ymm8 +vpxor 512(%rdi), %ymm9, %ymm9 +vpxor 544(%rdi), %ymm10, %ymm10 +vpxor 576(%rdi), %ymm11, %ymm11 +vpxor 608(%rdi), %ymm12, %ymm12 +vpxor 640(%rdi), %ymm8, %ymm8 +vpxor 672(%rdi), %ymm9, %ymm9 +vpxor 704(%rdi), %ymm10, %ymm10 +vpxor 736(%rdi), %ymm11, %ymm11 +vpxor 768(%rdi), %ymm12, %ymm12 +vpsllq $1, %ymm9, %ymm13 +vpsllq $1, %ymm10, %ymm14 +vpsllq $1, %ymm11, %ymm15 +vpsllq $1, %ymm12, %ymm7 +vpsllq $1, %ymm8, %ymm6 +vpsrlq $63, %ymm9, %ymm5 +vpsrlq $63, %ymm10, %ymm4 +vpsrlq $63, %ymm11, %ymm3 +vpsrlq $63, %ymm12, %ymm2 +vpsrlq $63, %ymm8, %ymm1 +vpor %ymm13, %ymm5, %ymm5 +vpor %ymm14, %ymm4, %ymm4 +vpor %ymm15, %ymm3, %ymm3 +vpor %ymm7, %ymm2, %ymm2 +vpor %ymm6, %ymm1, %ymm1 +vpxor %ymm5, %ymm12, %ymm5 +vpxor %ymm4, %ymm8, %ymm4 +vpxor %ymm3, %ymm9, %ymm3 +vpxor %ymm2, %ymm10, %ymm2 +vpxor %ymm1, %ymm11, %ymm1 +vpxor 0(%rdi), %ymm5, %ymm8 +vpxor 512(%rdi), %ymm4, %ymm9 +vpxor 224(%rdi), %ymm3, %ymm10 +vpxor 736(%rdi), %ymm2, %ymm11 +vpxor 448(%rdi), %ymm1, %ymm12 +vpsllq $44, %ymm9, %ymm14 +vpsllq $43, %ymm10, %ymm15 +vpsllq $21, %ymm11, %ymm7 +vpsllq $14, %ymm12, %ymm6 +vpsrlq $20, %ymm9, %ymm9 +vpsrlq $21, %ymm10, %ymm10 +vpsrlq $43, %ymm11, %ymm11 +vpsrlq $50, %ymm12, %ymm12 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vpbroadcastq 8(%rsi), %ymm8 +vpxor %ymm8, %ymm13, %ymm13 +vmovdqa %ymm13, 0(%rdi) +vmovdqa %ymm14, 512(%rdi) +vmovdqa %ymm15, 224(%rdi) +vmovdqa %ymm7, 736(%rdi) +vmovdqa %ymm6, 448(%rdi) +vpxor 576(%rdi), %ymm2, %ymm8 +vpxor 288(%rdi), %ymm1, %ymm9 +vpxor 640(%rdi), %ymm5, %ymm10 +vpxor 352(%rdi), %ymm4, %ymm11 +vpxor 64(%rdi), %ymm3, %ymm12 +vpsllq $28, %ymm8, %ymm13 +vpsllq $20, %ymm9, %ymm14 +vpsllq $3, %ymm10, %ymm15 +vpsllq $45, %ymm11, %ymm7 +vpsllq $61, %ymm12, %ymm6 +vpsrlq $36, %ymm8, %ymm8 +vpsrlq $44, %ymm9, %ymm9 +vpsrlq $61, %ymm10, %ymm10 +vpsrlq $19, %ymm11, %ymm11 +vpsrlq $3, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 640(%rdi) +vmovdqa %ymm14, 352(%rdi) +vmovdqa %ymm15, 64(%rdi) +vmovdqa %ymm7, 576(%rdi) +vmovdqa %ymm6, 288(%rdi) +vpxor 192(%rdi), %ymm4, %ymm8 +vpxor 704(%rdi), %ymm3, %ymm9 +vpxor 416(%rdi), %ymm2, %ymm10 +vpxor 128(%rdi), %ymm1, %ymm11 +vpxor 480(%rdi), %ymm5, %ymm12 +vpsllq $1, %ymm8, %ymm13 +vpsllq $6, %ymm9, %ymm14 +vpsllq $25, %ymm10, %ymm15 +#vpsllq $8, %ymm11, %ymm7 +vpsllq $18, %ymm12, %ymm6 +vpsrlq $63, %ymm8, %ymm8 +vpsrlq $58, %ymm9, %ymm9 +vpsrlq $39, %ymm10, %ymm10 +#vpsrlq $56, %ymm11, %ymm11 +vpsrlq $46, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +#vpor %ymm7, %ymm11, %ymm11 +vpshufb %ymm0, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 480(%rdi) +vmovdqa %ymm14, 192(%rdi) +vmovdqa %ymm15, 704(%rdi) +vmovdqa %ymm7, 416(%rdi) +vmovdqa %ymm6, 128(%rdi) +vpxor 768(%rdi), %ymm1, %ymm8 +vpxor 320(%rdi), %ymm5, %ymm9 +vpxor 32(%rdi), %ymm4, %ymm10 +vpxor 544(%rdi), %ymm3, %ymm11 +vpxor 256(%rdi), %ymm2, %ymm12 +vpsllq $27, %ymm8, %ymm13 +vpsllq $36, %ymm9, %ymm14 +vpsllq $10, %ymm10, %ymm15 +vpsllq $15, %ymm11, %ymm7 +#vpsllq $56, %ymm12, %ymm6 +vpsrlq $37, %ymm8, %ymm8 +vpsrlq $28, %ymm9, %ymm9 +vpsrlq $54, %ymm10, %ymm10 +vpsrlq $49, %ymm11, %ymm11 +#vpsrlq $8, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +#vpor %ymm6, %ymm12, %ymm12 +vpshufb rho56(%rip), %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 320(%rdi) +vmovdqa %ymm14, 32(%rdi) +vmovdqa %ymm15, 544(%rdi) +vmovdqa %ymm7, 256(%rdi) +vmovdqa %ymm6, 768(%rdi) +vpxor 384(%rdi), %ymm3, %ymm8 +vpxor 96(%rdi), %ymm2, %ymm9 +vpxor 608(%rdi), %ymm1, %ymm10 +vpxor 160(%rdi), %ymm5, %ymm11 +vpxor 672(%rdi), %ymm4, %ymm12 +vpsllq $62, %ymm8, %ymm13 +vpsllq $55, %ymm9, %ymm14 +vpsllq $39, %ymm10, %ymm15 +vpsllq $41, %ymm11, %ymm7 +vpsllq $2, %ymm12, %ymm6 +vpsrlq $2, %ymm8, %ymm8 +vpsrlq $9, %ymm9, %ymm9 +vpsrlq $25, %ymm10, %ymm10 +vpsrlq $23, %ymm11, %ymm11 +vpsrlq $62, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 160(%rdi) +vmovdqa %ymm14, 672(%rdi) +vmovdqa %ymm15, 384(%rdi) +vmovdqa %ymm7, 96(%rdi) +vmovdqa %ymm6, 608(%rdi) +vmovdqa 0(%rdi), %ymm8 +vmovdqa 32(%rdi), %ymm9 +vmovdqa 64(%rdi), %ymm10 +vmovdqa 96(%rdi), %ymm11 +vmovdqa 128(%rdi), %ymm12 +vpxor 160(%rdi), %ymm8, %ymm8 +vpxor 192(%rdi), %ymm9, %ymm9 +vpxor 224(%rdi), %ymm10, %ymm10 +vpxor 256(%rdi), %ymm11, %ymm11 +vpxor 288(%rdi), %ymm12, %ymm12 +vpxor 320(%rdi), %ymm8, %ymm8 +vpxor 352(%rdi), %ymm9, %ymm9 +vpxor 384(%rdi), %ymm10, %ymm10 +vpxor 416(%rdi), %ymm11, %ymm11 +vpxor 448(%rdi), %ymm12, %ymm12 +vpxor 480(%rdi), %ymm8, %ymm8 +vpxor 512(%rdi), %ymm9, %ymm9 +vpxor 544(%rdi), %ymm10, %ymm10 +vpxor 576(%rdi), %ymm11, %ymm11 +vpxor 608(%rdi), %ymm12, %ymm12 +vpxor 640(%rdi), %ymm8, %ymm8 +vpxor 672(%rdi), %ymm9, %ymm9 +vpxor 704(%rdi), %ymm10, %ymm10 +vpxor 736(%rdi), %ymm11, %ymm11 +vpxor 768(%rdi), %ymm12, %ymm12 +vpsllq $1, %ymm9, %ymm13 +vpsllq $1, %ymm10, %ymm14 +vpsllq $1, %ymm11, %ymm15 +vpsllq $1, %ymm12, %ymm7 +vpsllq $1, %ymm8, %ymm6 +vpsrlq $63, %ymm9, %ymm5 +vpsrlq $63, %ymm10, %ymm4 +vpsrlq $63, %ymm11, %ymm3 +vpsrlq $63, %ymm12, %ymm2 +vpsrlq $63, %ymm8, %ymm1 +vpor %ymm13, %ymm5, %ymm5 +vpor %ymm14, %ymm4, %ymm4 +vpor %ymm15, %ymm3, %ymm3 +vpor %ymm7, %ymm2, %ymm2 +vpor %ymm6, %ymm1, %ymm1 +vpxor %ymm5, %ymm12, %ymm5 +vpxor %ymm4, %ymm8, %ymm4 +vpxor %ymm3, %ymm9, %ymm3 +vpxor %ymm2, %ymm10, %ymm2 +vpxor %ymm1, %ymm11, %ymm1 +vpxor 0(%rdi), %ymm5, %ymm8 +vpxor 352(%rdi), %ymm4, %ymm9 +vpxor 704(%rdi), %ymm3, %ymm10 +vpxor 256(%rdi), %ymm2, %ymm11 +vpxor 608(%rdi), %ymm1, %ymm12 +vpsllq $44, %ymm9, %ymm14 +vpsllq $43, %ymm10, %ymm15 +vpsllq $21, %ymm11, %ymm7 +vpsllq $14, %ymm12, %ymm6 +vpsrlq $20, %ymm9, %ymm9 +vpsrlq $21, %ymm10, %ymm10 +vpsrlq $43, %ymm11, %ymm11 +vpsrlq $50, %ymm12, %ymm12 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vpbroadcastq 16(%rsi), %ymm8 +vpxor %ymm8, %ymm13, %ymm13 +vmovdqa %ymm13, 0(%rdi) +vmovdqa %ymm14, 352(%rdi) +vmovdqa %ymm15, 704(%rdi) +vmovdqa %ymm7, 256(%rdi) +vmovdqa %ymm6, 608(%rdi) +vpxor 736(%rdi), %ymm2, %ymm8 +vpxor 288(%rdi), %ymm1, %ymm9 +vpxor 480(%rdi), %ymm5, %ymm10 +vpxor 32(%rdi), %ymm4, %ymm11 +vpxor 384(%rdi), %ymm3, %ymm12 +vpsllq $28, %ymm8, %ymm13 +vpsllq $20, %ymm9, %ymm14 +vpsllq $3, %ymm10, %ymm15 +vpsllq $45, %ymm11, %ymm7 +vpsllq $61, %ymm12, %ymm6 +vpsrlq $36, %ymm8, %ymm8 +vpsrlq $44, %ymm9, %ymm9 +vpsrlq $61, %ymm10, %ymm10 +vpsrlq $19, %ymm11, %ymm11 +vpsrlq $3, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 480(%rdi) +vmovdqa %ymm14, 32(%rdi) +vmovdqa %ymm15, 384(%rdi) +vmovdqa %ymm7, 736(%rdi) +vmovdqa %ymm6, 288(%rdi) +vpxor 512(%rdi), %ymm4, %ymm8 +vpxor 64(%rdi), %ymm3, %ymm9 +vpxor 416(%rdi), %ymm2, %ymm10 +vpxor 768(%rdi), %ymm1, %ymm11 +vpxor 160(%rdi), %ymm5, %ymm12 +vpsllq $1, %ymm8, %ymm13 +vpsllq $6, %ymm9, %ymm14 +vpsllq $25, %ymm10, %ymm15 +#vpsllq $8, %ymm11, %ymm7 +vpsllq $18, %ymm12, %ymm6 +vpsrlq $63, %ymm8, %ymm8 +vpsrlq $58, %ymm9, %ymm9 +vpsrlq $39, %ymm10, %ymm10 +#vpsrlq $56, %ymm11, %ymm11 +vpsrlq $46, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +#vpor %ymm7, %ymm11, %ymm11 +vpshufb %ymm0, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 160(%rdi) +vmovdqa %ymm14, 512(%rdi) +vmovdqa %ymm15, 64(%rdi) +vmovdqa %ymm7, 416(%rdi) +vmovdqa %ymm6, 768(%rdi) +vpxor 448(%rdi), %ymm1, %ymm8 +vpxor 640(%rdi), %ymm5, %ymm9 +vpxor 192(%rdi), %ymm4, %ymm10 +vpxor 544(%rdi), %ymm3, %ymm11 +vpxor 96(%rdi), %ymm2, %ymm12 +vpsllq $27, %ymm8, %ymm13 +vpsllq $36, %ymm9, %ymm14 +vpsllq $10, %ymm10, %ymm15 +vpsllq $15, %ymm11, %ymm7 +#vpsllq $56, %ymm12, %ymm6 +vpsrlq $37, %ymm8, %ymm8 +vpsrlq $28, %ymm9, %ymm9 +vpsrlq $54, %ymm10, %ymm10 +vpsrlq $49, %ymm11, %ymm11 +#vpsrlq $8, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +#vpor %ymm6, %ymm12, %ymm12 +vpshufb rho56(%rip), %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 640(%rdi) +vmovdqa %ymm14, 192(%rdi) +vmovdqa %ymm15, 544(%rdi) +vmovdqa %ymm7, 96(%rdi) +vmovdqa %ymm6, 448(%rdi) +vpxor 224(%rdi), %ymm3, %ymm8 +vpxor 576(%rdi), %ymm2, %ymm9 +vpxor 128(%rdi), %ymm1, %ymm10 +vpxor 320(%rdi), %ymm5, %ymm11 +vpxor 672(%rdi), %ymm4, %ymm12 +vpsllq $62, %ymm8, %ymm13 +vpsllq $55, %ymm9, %ymm14 +vpsllq $39, %ymm10, %ymm15 +vpsllq $41, %ymm11, %ymm7 +vpsllq $2, %ymm12, %ymm6 +vpsrlq $2, %ymm8, %ymm8 +vpsrlq $9, %ymm9, %ymm9 +vpsrlq $25, %ymm10, %ymm10 +vpsrlq $23, %ymm11, %ymm11 +vpsrlq $62, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 320(%rdi) +vmovdqa %ymm14, 672(%rdi) +vmovdqa %ymm15, 224(%rdi) +vmovdqa %ymm7, 576(%rdi) +vmovdqa %ymm6, 128(%rdi) +vmovdqa 0(%rdi), %ymm8 +vmovdqa 32(%rdi), %ymm9 +vmovdqa 64(%rdi), %ymm10 +vmovdqa 96(%rdi), %ymm11 +vmovdqa 128(%rdi), %ymm12 +vpxor 160(%rdi), %ymm8, %ymm8 +vpxor 192(%rdi), %ymm9, %ymm9 +vpxor 224(%rdi), %ymm10, %ymm10 +vpxor 256(%rdi), %ymm11, %ymm11 +vpxor 288(%rdi), %ymm12, %ymm12 +vpxor 320(%rdi), %ymm8, %ymm8 +vpxor 352(%rdi), %ymm9, %ymm9 +vpxor 384(%rdi), %ymm10, %ymm10 +vpxor 416(%rdi), %ymm11, %ymm11 +vpxor 448(%rdi), %ymm12, %ymm12 +vpxor 480(%rdi), %ymm8, %ymm8 +vpxor 512(%rdi), %ymm9, %ymm9 +vpxor 544(%rdi), %ymm10, %ymm10 +vpxor 576(%rdi), %ymm11, %ymm11 +vpxor 608(%rdi), %ymm12, %ymm12 +vpxor 640(%rdi), %ymm8, %ymm8 +vpxor 672(%rdi), %ymm9, %ymm9 +vpxor 704(%rdi), %ymm10, %ymm10 +vpxor 736(%rdi), %ymm11, %ymm11 +vpxor 768(%rdi), %ymm12, %ymm12 +vpsllq $1, %ymm9, %ymm13 +vpsllq $1, %ymm10, %ymm14 +vpsllq $1, %ymm11, %ymm15 +vpsllq $1, %ymm12, %ymm7 +vpsllq $1, %ymm8, %ymm6 +vpsrlq $63, %ymm9, %ymm5 +vpsrlq $63, %ymm10, %ymm4 +vpsrlq $63, %ymm11, %ymm3 +vpsrlq $63, %ymm12, %ymm2 +vpsrlq $63, %ymm8, %ymm1 +vpor %ymm13, %ymm5, %ymm5 +vpor %ymm14, %ymm4, %ymm4 +vpor %ymm15, %ymm3, %ymm3 +vpor %ymm7, %ymm2, %ymm2 +vpor %ymm6, %ymm1, %ymm1 +vpxor %ymm5, %ymm12, %ymm5 +vpxor %ymm4, %ymm8, %ymm4 +vpxor %ymm3, %ymm9, %ymm3 +vpxor %ymm2, %ymm10, %ymm2 +vpxor %ymm1, %ymm11, %ymm1 +vpxor 0(%rdi), %ymm5, %ymm8 +vpxor 32(%rdi), %ymm4, %ymm9 +vpxor 64(%rdi), %ymm3, %ymm10 +vpxor 96(%rdi), %ymm2, %ymm11 +vpxor 128(%rdi), %ymm1, %ymm12 +vpsllq $44, %ymm9, %ymm14 +vpsllq $43, %ymm10, %ymm15 +vpsllq $21, %ymm11, %ymm7 +vpsllq $14, %ymm12, %ymm6 +vpsrlq $20, %ymm9, %ymm9 +vpsrlq $21, %ymm10, %ymm10 +vpsrlq $43, %ymm11, %ymm11 +vpsrlq $50, %ymm12, %ymm12 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vpbroadcastq 24(%rsi), %ymm8 +vpxor %ymm8, %ymm13, %ymm13 +vmovdqa %ymm13, 0(%rdi) +vmovdqa %ymm14, 32(%rdi) +vmovdqa %ymm15, 64(%rdi) +vmovdqa %ymm7, 96(%rdi) +vmovdqa %ymm6, 128(%rdi) +vpxor 256(%rdi), %ymm2, %ymm8 +vpxor 288(%rdi), %ymm1, %ymm9 +vpxor 160(%rdi), %ymm5, %ymm10 +vpxor 192(%rdi), %ymm4, %ymm11 +vpxor 224(%rdi), %ymm3, %ymm12 +vpsllq $28, %ymm8, %ymm13 +vpsllq $20, %ymm9, %ymm14 +vpsllq $3, %ymm10, %ymm15 +vpsllq $45, %ymm11, %ymm7 +vpsllq $61, %ymm12, %ymm6 +vpsrlq $36, %ymm8, %ymm8 +vpsrlq $44, %ymm9, %ymm9 +vpsrlq $61, %ymm10, %ymm10 +vpsrlq $19, %ymm11, %ymm11 +vpsrlq $3, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 160(%rdi) +vmovdqa %ymm14, 192(%rdi) +vmovdqa %ymm15, 224(%rdi) +vmovdqa %ymm7, 256(%rdi) +vmovdqa %ymm6, 288(%rdi) +vpxor 352(%rdi), %ymm4, %ymm8 +vpxor 384(%rdi), %ymm3, %ymm9 +vpxor 416(%rdi), %ymm2, %ymm10 +vpxor 448(%rdi), %ymm1, %ymm11 +vpxor 320(%rdi), %ymm5, %ymm12 +vpsllq $1, %ymm8, %ymm13 +vpsllq $6, %ymm9, %ymm14 +vpsllq $25, %ymm10, %ymm15 +#vpsllq $8, %ymm11, %ymm7 +vpsllq $18, %ymm12, %ymm6 +vpsrlq $63, %ymm8, %ymm8 +vpsrlq $58, %ymm9, %ymm9 +vpsrlq $39, %ymm10, %ymm10 +#vpsrlq $56, %ymm11, %ymm11 +vpsrlq $46, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +#vpor %ymm7, %ymm11, %ymm11 +vpshufb %ymm0, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 320(%rdi) +vmovdqa %ymm14, 352(%rdi) +vmovdqa %ymm15, 384(%rdi) +vmovdqa %ymm7, 416(%rdi) +vmovdqa %ymm6, 448(%rdi) +vpxor 608(%rdi), %ymm1, %ymm8 +vpxor 480(%rdi), %ymm5, %ymm9 +vpxor 512(%rdi), %ymm4, %ymm10 +vpxor 544(%rdi), %ymm3, %ymm11 +vpxor 576(%rdi), %ymm2, %ymm12 +vpsllq $27, %ymm8, %ymm13 +vpsllq $36, %ymm9, %ymm14 +vpsllq $10, %ymm10, %ymm15 +vpsllq $15, %ymm11, %ymm7 +#vpsllq $56, %ymm12, %ymm6 +vpsrlq $37, %ymm8, %ymm8 +vpsrlq $28, %ymm9, %ymm9 +vpsrlq $54, %ymm10, %ymm10 +vpsrlq $49, %ymm11, %ymm11 +#vpsrlq $8, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +#vpor %ymm6, %ymm12, %ymm12 +vpshufb rho56(%rip), %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 480(%rdi) +vmovdqa %ymm14, 512(%rdi) +vmovdqa %ymm15, 544(%rdi) +vmovdqa %ymm7, 576(%rdi) +vmovdqa %ymm6, 608(%rdi) +vpxor 704(%rdi), %ymm3, %ymm8 +vpxor 736(%rdi), %ymm2, %ymm9 +vpxor 768(%rdi), %ymm1, %ymm10 +vpxor 640(%rdi), %ymm5, %ymm11 +vpxor 672(%rdi), %ymm4, %ymm12 +vpsllq $62, %ymm8, %ymm13 +vpsllq $55, %ymm9, %ymm14 +vpsllq $39, %ymm10, %ymm15 +vpsllq $41, %ymm11, %ymm7 +vpsllq $2, %ymm12, %ymm6 +vpsrlq $2, %ymm8, %ymm8 +vpsrlq $9, %ymm9, %ymm9 +vpsrlq $25, %ymm10, %ymm10 +vpsrlq $23, %ymm11, %ymm11 +vpsrlq $62, %ymm12, %ymm12 +vpor %ymm13, %ymm8, %ymm8 +vpor %ymm14, %ymm9, %ymm9 +vpor %ymm15, %ymm10, %ymm10 +vpor %ymm7, %ymm11, %ymm11 +vpor %ymm6, %ymm12, %ymm12 +vpandn %ymm10, %ymm9, %ymm13 +vpandn %ymm11, %ymm10, %ymm14 +vpandn %ymm12, %ymm11, %ymm15 +vpandn %ymm8, %ymm12, %ymm7 +vpandn %ymm9, %ymm8, %ymm6 +vpxor %ymm8, %ymm13, %ymm13 +vpxor %ymm9, %ymm14, %ymm14 +vpxor %ymm10, %ymm15, %ymm15 +vpxor %ymm11, %ymm7, %ymm7 +vpxor %ymm12, %ymm6, %ymm6 +vmovdqa %ymm13, 640(%rdi) +vmovdqa %ymm14, 672(%rdi) +vmovdqa %ymm15, 704(%rdi) +vmovdqa %ymm7, 736(%rdi) +vmovdqa %ymm6, 768(%rdi) +addq $32, %rsi +subq $1, %rax +jnz looptop +ret + +.section .note.GNU-stack,"",@progbits diff --git a/avx2/fips202.c b/avx2/fips202.c new file mode 120000 index 0000000..da2fa42 --- /dev/null +++ b/avx2/fips202.c @@ -0,0 +1 @@ +../ref/fips202.c \ No newline at end of file diff --git a/avx2/fips202.h b/avx2/fips202.h new file mode 100644 index 0000000..72fb2c2 --- /dev/null +++ b/avx2/fips202.h @@ -0,0 +1,57 @@ +#ifndef FIPS202_H +#define FIPS202_H + +#include +#include + +#define SHAKE128_RATE 168 +#define SHAKE256_RATE 136 +#define SHA3_256_RATE 136 +#define SHA3_512_RATE 72 + +#define FIPS202_NAMESPACE(s) pqcrystals_dilithium_fips202_avx2_##s + +typedef struct { + uint64_t s[25]; + unsigned int pos; +} keccak_state; + +#define KeccakF_RoundConstants FIPS202_NAMESPACE(KeccakF_RoundConstants) +extern const uint64_t KeccakF_RoundConstants[]; + +#define shake128_init FIPS202_NAMESPACE(shake128_init) +void shake128_init(keccak_state *state); +#define shake128_absorb FIPS202_NAMESPACE(shake128_absorb) +void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake128_finalize FIPS202_NAMESPACE(shake128_finalize) +void shake128_finalize(keccak_state *state); +#define shake128_squeeze FIPS202_NAMESPACE(shake128_squeeze) +void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state); +#define shake128_absorb_once FIPS202_NAMESPACE(shake128_absorb_once) +void shake128_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake128_squeezeblocks FIPS202_NAMESPACE(shake128_squeezeblocks) +void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); + +#define shake256_init FIPS202_NAMESPACE(shake256_init) +void shake256_init(keccak_state *state); +#define shake256_absorb FIPS202_NAMESPACE(shake256_absorb) +void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake256_finalize FIPS202_NAMESPACE(shake256_finalize) +void shake256_finalize(keccak_state *state); +#define shake256_squeeze FIPS202_NAMESPACE(shake256_squeeze) +void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state); +#define shake256_absorb_once FIPS202_NAMESPACE(shake256_absorb_once) +void shake256_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake256_squeezeblocks FIPS202_NAMESPACE(shake256_squeezeblocks) +void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); + +#define shake128 FIPS202_NAMESPACE(shake128) +void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); +#define shake256 FIPS202_NAMESPACE(shake256) +void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); +#define sha3_256 FIPS202_NAMESPACE(sha3_256) +void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen); +#define sha3_512 FIPS202_NAMESPACE(sha3_512) +void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen); + +#endif diff --git a/avx2/fips202x4.c b/avx2/fips202x4.c new file mode 100644 index 0000000..2ffa691 --- /dev/null +++ b/avx2/fips202x4.c @@ -0,0 +1,196 @@ +#include +#include +#include +#include +#include "fips202.h" +#include "fips202x4.h" + +static void keccakx4_absorb_once(__m256i s[25], + unsigned int r, + const uint8_t *in0, + const uint8_t *in1, + const uint8_t *in2, + const uint8_t *in3, + size_t inlen, + uint8_t p) +{ + size_t i; + uint64_t pos = 0; + __m256i t, idx; + + for(i = 0; i < 25; ++i) + s[i] = _mm256_setzero_si256(); + + idx = _mm256_set_epi64x((long long)in3, (long long)in2, (long long)in1, (long long)in0); + while(inlen >= r) { + for(i = 0; i < r/8; ++i) { + t = _mm256_i64gather_epi64((long long *)pos, idx, 1); + s[i] = _mm256_xor_si256(s[i], t); + pos += 8; + } + inlen -= r; + + f1600x4(s, KeccakF_RoundConstants); + } + + for(i = 0; i < inlen/8; ++i) { + t = _mm256_i64gather_epi64((long long *)pos, idx, 1); + s[i] = _mm256_xor_si256(s[i], t); + pos += 8; + } + inlen -= 8*i; + + if(inlen) { + t = _mm256_i64gather_epi64((long long *)pos, idx, 1); + idx = _mm256_set1_epi64x((1ULL << (8*inlen)) - 1); + t = _mm256_and_si256(t, idx); + s[i] = _mm256_xor_si256(s[i], t); + } + + t = _mm256_set1_epi64x((uint64_t)p << 8*inlen); + s[i] = _mm256_xor_si256(s[i], t); + t = _mm256_set1_epi64x(1ULL << 63); + s[r/8 - 1] = _mm256_xor_si256(s[r/8 - 1], t); +} + +static void keccakx4_squeezeblocks(uint8_t *out0, + uint8_t *out1, + uint8_t *out2, + uint8_t *out3, + size_t nblocks, + unsigned int r, + __m256i s[25]) +{ + unsigned int i; + __m128d t; + + while(nblocks > 0) { + f1600x4(s, KeccakF_RoundConstants); + for(i=0; i < r/8; ++i) { + t = _mm_castsi128_pd(_mm256_castsi256_si128(s[i])); + _mm_storel_pd((__attribute__((__may_alias__)) double *)&out0[8*i], t); + _mm_storeh_pd((__attribute__((__may_alias__)) double *)&out1[8*i], t); + t = _mm_castsi128_pd(_mm256_extracti128_si256(s[i],1)); + _mm_storel_pd((__attribute__((__may_alias__)) double *)&out2[8*i], t); + _mm_storeh_pd((__attribute__((__may_alias__)) double *)&out3[8*i], t); + } + + out0 += r; + out1 += r; + out2 += r; + out3 += r; + --nblocks; + } +} + +void shake128x4_absorb_once(keccakx4_state *state, + const uint8_t *in0, + const uint8_t *in1, + const uint8_t *in2, + const uint8_t *in3, + size_t inlen) +{ + keccakx4_absorb_once(state->s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +} + +void shake128x4_squeezeblocks(uint8_t *out0, + uint8_t *out1, + uint8_t *out2, + uint8_t *out3, + size_t nblocks, + keccakx4_state *state) +{ + keccakx4_squeezeblocks(out0, out1, out2, out3, nblocks, SHAKE128_RATE, state->s); +} + +void shake256x4_absorb_once(keccakx4_state *state, + const uint8_t *in0, + const uint8_t *in1, + const uint8_t *in2, + const uint8_t *in3, + size_t inlen) +{ + keccakx4_absorb_once(state->s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +} + +void shake256x4_squeezeblocks(uint8_t *out0, + uint8_t *out1, + uint8_t *out2, + uint8_t *out3, + size_t nblocks, + keccakx4_state *state) +{ + keccakx4_squeezeblocks(out0, out1, out2, out3, nblocks, SHAKE256_RATE, state->s); +} + +void shake128x4(uint8_t *out0, + uint8_t *out1, + uint8_t *out2, + uint8_t *out3, + size_t outlen, + const uint8_t *in0, + const uint8_t *in1, + const uint8_t *in2, + const uint8_t *in3, + size_t inlen) +{ + unsigned int i; + size_t nblocks = outlen/SHAKE128_RATE; + uint8_t t[4][SHAKE128_RATE]; + keccakx4_state state; + + shake128x4_absorb_once(&state, in0, in1, in2, in3, inlen); + shake128x4_squeezeblocks(out0, out1, out2, out3, nblocks, &state); + + out0 += nblocks*SHAKE128_RATE; + out1 += nblocks*SHAKE128_RATE; + out2 += nblocks*SHAKE128_RATE; + out3 += nblocks*SHAKE128_RATE; + outlen -= nblocks*SHAKE128_RATE; + + if(outlen) { + shake128x4_squeezeblocks(t[0], t[1], t[2], t[3], 1, &state); + for(i = 0; i < outlen; ++i) { + out0[i] = t[0][i]; + out1[i] = t[1][i]; + out2[i] = t[2][i]; + out3[i] = t[3][i]; + } + } +} + +void shake256x4(uint8_t *out0, + uint8_t *out1, + uint8_t *out2, + uint8_t *out3, + size_t outlen, + const uint8_t *in0, + const uint8_t *in1, + const uint8_t *in2, + const uint8_t *in3, + size_t inlen) +{ + unsigned int i; + size_t nblocks = outlen/SHAKE256_RATE; + uint8_t t[4][SHAKE256_RATE]; + keccakx4_state state; + + shake256x4_absorb_once(&state, in0, in1, in2, in3, inlen); + shake256x4_squeezeblocks(out0, out1, out2, out3, nblocks, &state); + + out0 += nblocks*SHAKE256_RATE; + out1 += nblocks*SHAKE256_RATE; + out2 += nblocks*SHAKE256_RATE; + out3 += nblocks*SHAKE256_RATE; + outlen -= nblocks*SHAKE256_RATE; + + if(outlen) { + shake256x4_squeezeblocks(t[0], t[1], t[2], t[3], 1, &state); + for(i = 0; i < outlen; ++i) { + out0[i] = t[0][i]; + out1[i] = t[1][i]; + out2[i] = t[2][i]; + out3[i] = t[3][i]; + } + } +} diff --git a/avx2/fips202x4.h b/avx2/fips202x4.h new file mode 100644 index 0000000..3288a3a --- /dev/null +++ b/avx2/fips202x4.h @@ -0,0 +1,91 @@ +#ifndef FIPS202X4_H +#define FIPS202X4_H + +#define FIPS202X4_NAMESPACE(s) pqcrystals_dilithium_fips202x4_avx2_##s + +#ifdef __ASSEMBLER__ +/* The C ABI on MacOS exports all symbols with a leading + * underscore. This means that any symbols we refer to from + * C files (functions) can't be found, and all symbols we + * refer to from ASM also can't be found. + * + * This define helps us get around this + */ +#if defined(__WIN32__) || defined(__APPLE__) +#define decorate(s) _##s +#define _cdecl(s) decorate(s) +#define cdecl(s) _cdecl(FIPS202X4_NAMESPACE(##s)) +#else +#define cdecl(s) FIPS202X4_NAMESPACE(##s) +#endif + +#else +#include +#include +#include + +typedef struct { + __m256i s[25]; +} keccakx4_state; + +#define f1600x4 FIPS202X4_NAMESPACE(f1600x4) +void f1600x4(__m256i *s, const uint64_t *rc); + +#define shake128x4_absorb_once FIPS202X4_NAMESPACE(shake128x4_absorb_once) +void shake128x4_absorb_once(keccakx4_state *state, + const uint8_t *in0, + const uint8_t *in1, + const uint8_t *in2, + const uint8_t *in3, + size_t inlen); + +#define shake128x4_squeezeblocks FIPS202X4_NAMESPACE(shake128x4_squeezeblocks) +void shake128x4_squeezeblocks(uint8_t *out0, + uint8_t *out1, + uint8_t *out2, + uint8_t *out3, + size_t nblocks, + keccakx4_state *state); + +#define shake256x4_absorb_once FIPS202X4_NAMESPACE(shake256x4_absorb_once) +void shake256x4_absorb_once(keccakx4_state *state, + const uint8_t *in0, + const uint8_t *in1, + const uint8_t *in2, + const uint8_t *in3, + size_t inlen); + +#define shake256x4_squeezeblocks FIPS202X4_NAMESPACE(shake256x4_squeezeblocks) +void shake256x4_squeezeblocks(uint8_t *out0, + uint8_t *out1, + uint8_t *out2, + uint8_t *out3, + size_t nblocks, + keccakx4_state *state); + +#define shake128x4 FIPS202X4_NAMESPACE(shake128x4) +void shake128x4(uint8_t *out0, + uint8_t *out1, + uint8_t *out2, + uint8_t *out3, + size_t outlen, + const uint8_t *in0, + const uint8_t *in1, + const uint8_t *in2, + const uint8_t *in3, + size_t inlen); + +#define shake256x4 FIPS202X4_NAMESPACE(shake256x4) +void shake256x4(uint8_t *out0, + uint8_t *out1, + uint8_t *out2, + uint8_t *out3, + size_t outlen, + const uint8_t *in0, + const uint8_t *in1, + const uint8_t *in2, + const uint8_t *in3, + size_t inlen); + +#endif +#endif diff --git a/avx2/invntt.S b/avx2/invntt.S new file mode 100644 index 0000000..d40ca13 --- /dev/null +++ b/avx2/invntt.S @@ -0,0 +1,240 @@ +#include "consts.h" +.include "shuffle.inc" + +.macro butterfly l,h,zl0=1,zl1=1,zh0=2,zh1=2 +vpsubd %ymm\l,%ymm\h,%ymm12 +vpaddd %ymm\h,%ymm\l,%ymm\l + +vpmuldq %ymm\zl0,%ymm12,%ymm13 +vmovshdup %ymm12,%ymm\h +vpmuldq %ymm\zl1,%ymm\h,%ymm14 + +vpmuldq %ymm\zh0,%ymm12,%ymm12 +vpmuldq %ymm\zh1,%ymm\h,%ymm\h + +vpmuldq %ymm0,%ymm13,%ymm13 +vpmuldq %ymm0,%ymm14,%ymm14 + +vpsubd %ymm13,%ymm12,%ymm12 +vpsubd %ymm14,%ymm\h,%ymm\h + +vmovshdup %ymm12,%ymm12 +vpblendd $0xAA,%ymm\h,%ymm12,%ymm\h +.endm + +.macro levels0t5 off +vmovdqa 256*\off+ 0(%rdi),%ymm4 +vmovdqa 256*\off+ 32(%rdi),%ymm5 +vmovdqa 256*\off+ 64(%rdi),%ymm6 +vmovdqa 256*\off+ 96(%rdi),%ymm7 +vmovdqa 256*\off+128(%rdi),%ymm8 +vmovdqa 256*\off+160(%rdi),%ymm9 +vmovdqa 256*\off+192(%rdi),%ymm10 +vmovdqa 256*\off+224(%rdi),%ymm11 + +/* level 0 */ +vpermq $0x1B,(_ZETAS_QINV+296-8*\off-8)*4(%rsi),%ymm3 +vpermq $0x1B,(_ZETAS+296-8*\off-8)*4(%rsi),%ymm15 +vmovshdup %ymm3,%ymm1 +vmovshdup %ymm15,%ymm2 +butterfly 4,5,1,3,2,15 + +vpermq $0x1B,(_ZETAS_QINV+296-8*\off-40)*4(%rsi),%ymm3 +vpermq $0x1B,(_ZETAS+296-8*\off-40)*4(%rsi),%ymm15 +vmovshdup %ymm3,%ymm1 +vmovshdup %ymm15,%ymm2 +butterfly 6,7,1,3,2,15 + +vpermq $0x1B,(_ZETAS_QINV+296-8*\off-72)*4(%rsi),%ymm3 +vpermq $0x1B,(_ZETAS+296-8*\off-72)*4(%rsi),%ymm15 +vmovshdup %ymm3,%ymm1 +vmovshdup %ymm15,%ymm2 +butterfly 8,9,1,3,2,15 + +vpermq $0x1B,(_ZETAS_QINV+296-8*\off-104)*4(%rsi),%ymm3 +vpermq $0x1B,(_ZETAS+296-8*\off-104)*4(%rsi),%ymm15 +vmovshdup %ymm3,%ymm1 +vmovshdup %ymm15,%ymm2 +butterfly 10,11,1,3,2,15 + +/* level 1 */ +vpermq $0x1B,(_ZETAS_QINV+168-8*\off-8)*4(%rsi),%ymm3 +vpermq $0x1B,(_ZETAS+168-8*\off-8)*4(%rsi),%ymm15 +vmovshdup %ymm3,%ymm1 +vmovshdup %ymm15,%ymm2 +butterfly 4,6,1,3,2,15 +butterfly 5,7,1,3,2,15 + +vpermq $0x1B,(_ZETAS_QINV+168-8*\off-40)*4(%rsi),%ymm3 +vpermq $0x1B,(_ZETAS+168-8*\off-40)*4(%rsi),%ymm15 +vmovshdup %ymm3,%ymm1 +vmovshdup %ymm15,%ymm2 +butterfly 8,10,1,3,2,15 +butterfly 9,11,1,3,2,15 + +/* level 2 */ +vpermq $0x1B,(_ZETAS_QINV+104-8*\off-8)*4(%rsi),%ymm3 +vpermq $0x1B,(_ZETAS+104-8*\off-8)*4(%rsi),%ymm15 +vmovshdup %ymm3,%ymm1 +vmovshdup %ymm15,%ymm2 +butterfly 4,8,1,3,2,15 +butterfly 5,9,1,3,2,15 +butterfly 6,10,1,3,2,15 +butterfly 7,11,1,3,2,15 + +/* level 3 */ +shuffle2 4,5,3,5 +shuffle2 6,7,4,7 +shuffle2 8,9,6,9 +shuffle2 10,11,8,11 + +vpermq $0x1B,(_ZETAS_QINV+72-8*\off-8)*4(%rsi),%ymm1 +vpermq $0x1B,(_ZETAS+72-8*\off-8)*4(%rsi),%ymm2 +butterfly 3,5 +butterfly 4,7 +butterfly 6,9 +butterfly 8,11 + +/* level 4 */ +shuffle4 3,4,10,4 +shuffle4 6,8,3,8 +shuffle4 5,7,6,7 +shuffle4 9,11,5,11 + +vpermq $0x1B,(_ZETAS_QINV+40-8*\off-8)*4(%rsi),%ymm1 +vpermq $0x1B,(_ZETAS+40-8*\off-8)*4(%rsi),%ymm2 +butterfly 10,4 +butterfly 3,8 +butterfly 6,7 +butterfly 5,11 + +/* level 5 */ +shuffle8 10,3,9,3 +shuffle8 6,5,10,5 +shuffle8 4,8,6,8 +shuffle8 7,11,4,11 + +vpbroadcastd (_ZETAS_QINV+7-\off)*4(%rsi),%ymm1 +vpbroadcastd (_ZETAS+7-\off)*4(%rsi),%ymm2 +butterfly 9,3 +butterfly 10,5 +butterfly 6,8 +butterfly 4,11 + +vmovdqa %ymm9,256*\off+ 0(%rdi) +vmovdqa %ymm10,256*\off+ 32(%rdi) +vmovdqa %ymm6,256*\off+ 64(%rdi) +vmovdqa %ymm4,256*\off+ 96(%rdi) +vmovdqa %ymm3,256*\off+128(%rdi) +vmovdqa %ymm5,256*\off+160(%rdi) +vmovdqa %ymm8,256*\off+192(%rdi) +vmovdqa %ymm11,256*\off+224(%rdi) +.endm + +.macro levels6t7 off +vmovdqa 0+32*\off(%rdi),%ymm4 +vmovdqa 128+32*\off(%rdi),%ymm5 +vmovdqa 256+32*\off(%rdi),%ymm6 +vmovdqa 384+32*\off(%rdi),%ymm7 +vmovdqa 512+32*\off(%rdi),%ymm8 +vmovdqa 640+32*\off(%rdi),%ymm9 +vmovdqa 768+32*\off(%rdi),%ymm10 +vmovdqa 896+32*\off(%rdi),%ymm11 + +/* level 6 */ +vpbroadcastd (_ZETAS_QINV+3)*4(%rsi),%ymm1 +vpbroadcastd (_ZETAS+3)*4(%rsi),%ymm2 +butterfly 4,6 +butterfly 5,7 + +vpbroadcastd (_ZETAS_QINV+2)*4(%rsi),%ymm1 +vpbroadcastd (_ZETAS+2)*4(%rsi),%ymm2 +butterfly 8,10 +butterfly 9,11 + +/* level 7 */ +vpbroadcastd (_ZETAS_QINV+0)*4(%rsi),%ymm1 +vpbroadcastd (_ZETAS+0)*4(%rsi),%ymm2 + +butterfly 4,8 +butterfly 5,9 +butterfly 6,10 +butterfly 7,11 + +vmovdqa %ymm8,512+32*\off(%rdi) +vmovdqa %ymm9,640+32*\off(%rdi) +vmovdqa %ymm10,768+32*\off(%rdi) +vmovdqa %ymm11,896+32*\off(%rdi) + +vmovdqa (_8XDIV_QINV)*4(%rsi),%ymm1 +vmovdqa (_8XDIV)*4(%rsi),%ymm2 +vpmuldq %ymm1,%ymm4,%ymm12 +vpmuldq %ymm1,%ymm5,%ymm13 +vmovshdup %ymm4,%ymm8 +vmovshdup %ymm5,%ymm9 +vpmuldq %ymm1,%ymm8,%ymm14 +vpmuldq %ymm1,%ymm9,%ymm15 +vpmuldq %ymm2,%ymm4,%ymm4 +vpmuldq %ymm2,%ymm5,%ymm5 +vpmuldq %ymm2,%ymm8,%ymm8 +vpmuldq %ymm2,%ymm9,%ymm9 +vpmuldq %ymm0,%ymm12,%ymm12 +vpmuldq %ymm0,%ymm13,%ymm13 +vpmuldq %ymm0,%ymm14,%ymm14 +vpmuldq %ymm0,%ymm15,%ymm15 +vpsubd %ymm12,%ymm4,%ymm4 +vpsubd %ymm13,%ymm5,%ymm5 +vpsubd %ymm14,%ymm8,%ymm8 +vpsubd %ymm15,%ymm9,%ymm9 +vmovshdup %ymm4,%ymm4 +vmovshdup %ymm5,%ymm5 +vpblendd $0xAA,%ymm8,%ymm4,%ymm4 +vpblendd $0xAA,%ymm9,%ymm5,%ymm5 + +vpmuldq %ymm1,%ymm6,%ymm12 +vpmuldq %ymm1,%ymm7,%ymm13 +vmovshdup %ymm6,%ymm8 +vmovshdup %ymm7,%ymm9 +vpmuldq %ymm1,%ymm8,%ymm14 +vpmuldq %ymm1,%ymm9,%ymm15 +vpmuldq %ymm2,%ymm6,%ymm6 +vpmuldq %ymm2,%ymm7,%ymm7 +vpmuldq %ymm2,%ymm8,%ymm8 +vpmuldq %ymm2,%ymm9,%ymm9 +vpmuldq %ymm0,%ymm12,%ymm12 +vpmuldq %ymm0,%ymm13,%ymm13 +vpmuldq %ymm0,%ymm14,%ymm14 +vpmuldq %ymm0,%ymm15,%ymm15 +vpsubd %ymm12,%ymm6,%ymm6 +vpsubd %ymm13,%ymm7,%ymm7 +vpsubd %ymm14,%ymm8,%ymm8 +vpsubd %ymm15,%ymm9,%ymm9 +vmovshdup %ymm6,%ymm6 +vmovshdup %ymm7,%ymm7 +vpblendd $0xAA,%ymm8,%ymm6,%ymm6 +vpblendd $0xAA,%ymm9,%ymm7,%ymm7 + +vmovdqa %ymm4, 0+32*\off(%rdi) +vmovdqa %ymm5,128+32*\off(%rdi) +vmovdqa %ymm6,256+32*\off(%rdi) +vmovdqa %ymm7,384+32*\off(%rdi) +.endm + +.text +.global cdecl(invntt_avx) +cdecl(invntt_avx): +vmovdqa _8XQ*4(%rsi),%ymm0 + +levels0t5 0 +levels0t5 1 +levels0t5 2 +levels0t5 3 + +levels6t7 0 +levels6t7 1 +levels6t7 2 +levels6t7 3 + +ret + +.section .note.GNU-stack,"",@progbits diff --git a/avx2/ntt.S b/avx2/ntt.S new file mode 100644 index 0000000..026f057 --- /dev/null +++ b/avx2/ntt.S @@ -0,0 +1,198 @@ +#include "consts.h" +.include "shuffle.inc" + +.macro butterfly l,h,zl0=1,zl1=1,zh0=2,zh1=2 +vpmuldq %ymm\zl0,%ymm\h,%ymm13 +vmovshdup %ymm\h,%ymm12 +vpmuldq %ymm\zl1,%ymm12,%ymm14 + +vpmuldq %ymm\zh0,%ymm\h,%ymm\h +vpmuldq %ymm\zh1,%ymm12,%ymm12 + +vpmuldq %ymm0,%ymm13,%ymm13 +vpmuldq %ymm0,%ymm14,%ymm14 + +vmovshdup %ymm\h,%ymm\h +vpblendd $0xAA,%ymm12,%ymm\h,%ymm\h + +vpsubd %ymm\h,%ymm\l,%ymm12 +vpaddd %ymm\h,%ymm\l,%ymm\l + +vmovshdup %ymm13,%ymm13 +vpblendd $0xAA,%ymm14,%ymm13,%ymm13 + +vpaddd %ymm13,%ymm12,%ymm\h +vpsubd %ymm13,%ymm\l,%ymm\l +.endm + +.macro levels0t1 off +/* level 0 */ +vpbroadcastd (_ZETAS_QINV+1)*4(%rsi),%ymm1 +vpbroadcastd (_ZETAS+1)*4(%rsi),%ymm2 + +vmovdqa 0+32*\off(%rdi),%ymm4 +vmovdqa 128+32*\off(%rdi),%ymm5 +vmovdqa 256+32*\off(%rdi),%ymm6 +vmovdqa 384+32*\off(%rdi),%ymm7 +vmovdqa 512+32*\off(%rdi),%ymm8 +vmovdqa 640+32*\off(%rdi),%ymm9 +vmovdqa 768+32*\off(%rdi),%ymm10 +vmovdqa 896+32*\off(%rdi),%ymm11 + +butterfly 4,8 +butterfly 5,9 +butterfly 6,10 +butterfly 7,11 + +/* level 1 */ +vpbroadcastd (_ZETAS_QINV+2)*4(%rsi),%ymm1 +vpbroadcastd (_ZETAS+2)*4(%rsi),%ymm2 +butterfly 4,6 +butterfly 5,7 + +vpbroadcastd (_ZETAS_QINV+3)*4(%rsi),%ymm1 +vpbroadcastd (_ZETAS+3)*4(%rsi),%ymm2 +butterfly 8,10 +butterfly 9,11 + +vmovdqa %ymm4, 0+32*\off(%rdi) +vmovdqa %ymm5,128+32*\off(%rdi) +vmovdqa %ymm6,256+32*\off(%rdi) +vmovdqa %ymm7,384+32*\off(%rdi) +vmovdqa %ymm8,512+32*\off(%rdi) +vmovdqa %ymm9,640+32*\off(%rdi) +vmovdqa %ymm10,768+32*\off(%rdi) +vmovdqa %ymm11,896+32*\off(%rdi) +.endm + +.macro levels2t7 off +/* level 2 */ +vmovdqa 256*\off+ 0(%rdi),%ymm4 +vmovdqa 256*\off+ 32(%rdi),%ymm5 +vmovdqa 256*\off+ 64(%rdi),%ymm6 +vmovdqa 256*\off+ 96(%rdi),%ymm7 +vmovdqa 256*\off+128(%rdi),%ymm8 +vmovdqa 256*\off+160(%rdi),%ymm9 +vmovdqa 256*\off+192(%rdi),%ymm10 +vmovdqa 256*\off+224(%rdi),%ymm11 + +vpbroadcastd (_ZETAS_QINV+4+\off)*4(%rsi),%ymm1 +vpbroadcastd (_ZETAS+4+\off)*4(%rsi),%ymm2 + +butterfly 4,8 +butterfly 5,9 +butterfly 6,10 +butterfly 7,11 + +shuffle8 4,8,3,8 +shuffle8 5,9,4,9 +shuffle8 6,10,5,10 +shuffle8 7,11,6,11 + +/* level 3 */ +vmovdqa (_ZETAS_QINV+8+8*\off)*4(%rsi),%ymm1 +vmovdqa (_ZETAS+8+8*\off)*4(%rsi),%ymm2 + +butterfly 3,5 +butterfly 8,10 +butterfly 4,6 +butterfly 9,11 + +shuffle4 3,5,7,5 +shuffle4 8,10,3,10 +shuffle4 4,6,8,6 +shuffle4 9,11,4,11 + +/* level 4 */ +vmovdqa (_ZETAS_QINV+40+8*\off)*4(%rsi),%ymm1 +vmovdqa (_ZETAS+40+8*\off)*4(%rsi),%ymm2 + +butterfly 7,8 +butterfly 5,6 +butterfly 3,4 +butterfly 10,11 + +shuffle2 7,8,9,8 +shuffle2 5,6,7,6 +shuffle2 3,4,5,4 +shuffle2 10,11,3,11 + +/* level 5 */ +vmovdqa (_ZETAS_QINV+72+8*\off)*4(%rsi),%ymm1 +vmovdqa (_ZETAS+72+8*\off)*4(%rsi),%ymm2 +vpsrlq $32,%ymm1,%ymm10 +vmovshdup %ymm2,%ymm15 + +butterfly 9,5,1,10,2,15 +butterfly 8,4,1,10,2,15 +butterfly 7,3,1,10,2,15 +butterfly 6,11,1,10,2,15 + +/* level 6 */ +vmovdqa (_ZETAS_QINV+104+8*\off)*4(%rsi),%ymm1 +vmovdqa (_ZETAS+104+8*\off)*4(%rsi),%ymm2 +vpsrlq $32,%ymm1,%ymm10 +vmovshdup %ymm2,%ymm15 +butterfly 9,7,1,10,2,15 +butterfly 8,6,1,10,2,15 + +vmovdqa (_ZETAS_QINV+104+8*\off+32)*4(%rsi),%ymm1 +vmovdqa (_ZETAS+104+8*\off+32)*4(%rsi),%ymm2 +vpsrlq $32,%ymm1,%ymm10 +vmovshdup %ymm2,%ymm15 +butterfly 5,3,1,10,2,15 +butterfly 4,11,1,10,2,15 + +/* level 7 */ +vmovdqa (_ZETAS_QINV+168+8*\off)*4(%rsi),%ymm1 +vmovdqa (_ZETAS+168+8*\off)*4(%rsi),%ymm2 +vpsrlq $32,%ymm1,%ymm10 +vmovshdup %ymm2,%ymm15 +butterfly 9,8,1,10,2,15 + +vmovdqa (_ZETAS_QINV+168+8*\off+32)*4(%rsi),%ymm1 +vmovdqa (_ZETAS+168+8*\off+32)*4(%rsi),%ymm2 +vpsrlq $32,%ymm1,%ymm10 +vmovshdup %ymm2,%ymm15 +butterfly 7,6,1,10,2,15 + +vmovdqa (_ZETAS_QINV+168+8*\off+64)*4(%rsi),%ymm1 +vmovdqa (_ZETAS+168+8*\off+64)*4(%rsi),%ymm2 +vpsrlq $32,%ymm1,%ymm10 +vmovshdup %ymm2,%ymm15 +butterfly 5,4,1,10,2,15 + +vmovdqa (_ZETAS_QINV+168+8*\off+96)*4(%rsi),%ymm1 +vmovdqa (_ZETAS+168+8*\off+96)*4(%rsi),%ymm2 +vpsrlq $32,%ymm1,%ymm10 +vmovshdup %ymm2,%ymm15 +butterfly 3,11,1,10,2,15 + +vmovdqa %ymm9,256*\off+ 0(%rdi) +vmovdqa %ymm8,256*\off+ 32(%rdi) +vmovdqa %ymm7,256*\off+ 64(%rdi) +vmovdqa %ymm6,256*\off+ 96(%rdi) +vmovdqa %ymm5,256*\off+128(%rdi) +vmovdqa %ymm4,256*\off+160(%rdi) +vmovdqa %ymm3,256*\off+192(%rdi) +vmovdqa %ymm11,256*\off+224(%rdi) +.endm + +.text +.global cdecl(ntt_avx) +cdecl(ntt_avx): +vmovdqa _8XQ*4(%rsi),%ymm0 + +levels0t1 0 +levels0t1 1 +levels0t1 2 +levels0t1 3 + +levels2t7 0 +levels2t7 1 +levels2t7 2 +levels2t7 3 + +ret + +.section .note.GNU-stack,"",@progbits diff --git a/avx2/ntt.h b/avx2/ntt.h new file mode 100644 index 0000000..0c4fbdd --- /dev/null +++ b/avx2/ntt.h @@ -0,0 +1,19 @@ +#ifndef NTT_H +#define NTT_H + +#include + +#define ntt_avx DILITHIUM_NAMESPACE(ntt_avx) +void ntt_avx(__m256i *a, const __m256i *qdata); +#define invntt_avx DILITHIUM_NAMESPACE(invntt_avx) +void invntt_avx(__m256i *a, const __m256i *qdata); + +#define nttunpack_avx DILITHIUM_NAMESPACE(nttunpack_avx) +void nttunpack_avx(__m256i *a); + +#define pointwise_avx DILITHIUM_NAMESPACE(pointwise_avx) +void pointwise_avx(__m256i *c, const __m256i *a, const __m256i *b, const __m256i *qdata); +#define pointwise_acc_avx DILITHIUM_NAMESPACE(pointwise_acc_avx) +void pointwise_acc_avx(__m256i *c, const __m256i *a, const __m256i *b, const __m256i *qdata); + +#endif diff --git a/avx2/packing.c b/avx2/packing.c new file mode 120000 index 0000000..e77fac9 --- /dev/null +++ b/avx2/packing.c @@ -0,0 +1 @@ +../ref/packing.c \ No newline at end of file diff --git a/avx2/packing.h b/avx2/packing.h new file mode 120000 index 0000000..d27a8e9 --- /dev/null +++ b/avx2/packing.h @@ -0,0 +1 @@ +../ref/packing.h \ No newline at end of file diff --git a/avx2/params.h b/avx2/params.h new file mode 120000 index 0000000..53133cc --- /dev/null +++ b/avx2/params.h @@ -0,0 +1 @@ +../ref/params.h \ No newline at end of file diff --git a/avx2/pointwise.S b/avx2/pointwise.S new file mode 100644 index 0000000..6b687c7 --- /dev/null +++ b/avx2/pointwise.S @@ -0,0 +1,213 @@ +#include "params.h" +#include "consts.h" + +.text +.global cdecl(pointwise_avx) +cdecl(pointwise_avx): +#consts +vmovdqa _8XQINV*4(%rcx),%ymm0 +vmovdqa _8XQ*4(%rcx),%ymm1 + +xor %eax,%eax +_looptop1: +#load +vmovdqa (%rsi),%ymm2 +vmovdqa 32(%rsi),%ymm4 +vmovdqa 64(%rsi),%ymm6 +vmovdqa (%rdx),%ymm10 +vmovdqa 32(%rdx),%ymm12 +vmovdqa 64(%rdx),%ymm14 +vpsrlq $32,%ymm2,%ymm3 +vpsrlq $32,%ymm4,%ymm5 +vmovshdup %ymm6,%ymm7 +vpsrlq $32,%ymm10,%ymm11 +vpsrlq $32,%ymm12,%ymm13 +vmovshdup %ymm14,%ymm15 + +#mul +vpmuldq %ymm2,%ymm10,%ymm2 +vpmuldq %ymm3,%ymm11,%ymm3 +vpmuldq %ymm4,%ymm12,%ymm4 +vpmuldq %ymm5,%ymm13,%ymm5 +vpmuldq %ymm6,%ymm14,%ymm6 +vpmuldq %ymm7,%ymm15,%ymm7 + +#reduce +vpmuldq %ymm0,%ymm2,%ymm10 +vpmuldq %ymm0,%ymm3,%ymm11 +vpmuldq %ymm0,%ymm4,%ymm12 +vpmuldq %ymm0,%ymm5,%ymm13 +vpmuldq %ymm0,%ymm6,%ymm14 +vpmuldq %ymm0,%ymm7,%ymm15 +vpmuldq %ymm1,%ymm10,%ymm10 +vpmuldq %ymm1,%ymm11,%ymm11 +vpmuldq %ymm1,%ymm12,%ymm12 +vpmuldq %ymm1,%ymm13,%ymm13 +vpmuldq %ymm1,%ymm14,%ymm14 +vpmuldq %ymm1,%ymm15,%ymm15 +vpsubq %ymm10,%ymm2,%ymm2 +vpsubq %ymm11,%ymm3,%ymm3 +vpsubq %ymm12,%ymm4,%ymm4 +vpsubq %ymm13,%ymm5,%ymm5 +vpsubq %ymm14,%ymm6,%ymm6 +vpsubq %ymm15,%ymm7,%ymm7 +vpsrlq $32,%ymm2,%ymm2 +vpsrlq $32,%ymm4,%ymm4 +vmovshdup %ymm6,%ymm6 + +#store +vpblendd $0xAA,%ymm3,%ymm2,%ymm2 +vpblendd $0xAA,%ymm5,%ymm4,%ymm4 +vpblendd $0xAA,%ymm7,%ymm6,%ymm6 +vmovdqa %ymm2,(%rdi) +vmovdqa %ymm4,32(%rdi) +vmovdqa %ymm6,64(%rdi) + +add $96,%rdi +add $96,%rsi +add $96,%rdx +add $1,%eax +cmp $10,%eax +jb _looptop1 + +vmovdqa (%rsi),%ymm2 +vmovdqa 32(%rsi),%ymm4 +vmovdqa (%rdx),%ymm10 +vmovdqa 32(%rdx),%ymm12 +vpsrlq $32,%ymm2,%ymm3 +vpsrlq $32,%ymm4,%ymm5 +vmovshdup %ymm10,%ymm11 +vmovshdup %ymm12,%ymm13 + +#mul +vpmuldq %ymm2,%ymm10,%ymm2 +vpmuldq %ymm3,%ymm11,%ymm3 +vpmuldq %ymm4,%ymm12,%ymm4 +vpmuldq %ymm5,%ymm13,%ymm5 + +#reduce +vpmuldq %ymm0,%ymm2,%ymm10 +vpmuldq %ymm0,%ymm3,%ymm11 +vpmuldq %ymm0,%ymm4,%ymm12 +vpmuldq %ymm0,%ymm5,%ymm13 +vpmuldq %ymm1,%ymm10,%ymm10 +vpmuldq %ymm1,%ymm11,%ymm11 +vpmuldq %ymm1,%ymm12,%ymm12 +vpmuldq %ymm1,%ymm13,%ymm13 +vpsubq %ymm10,%ymm2,%ymm2 +vpsubq %ymm11,%ymm3,%ymm3 +vpsubq %ymm12,%ymm4,%ymm4 +vpsubq %ymm13,%ymm5,%ymm5 +vpsrlq $32,%ymm2,%ymm2 +vmovshdup %ymm4,%ymm4 + +#store +vpblendd $0x55,%ymm2,%ymm3,%ymm2 +vpblendd $0x55,%ymm4,%ymm5,%ymm4 +vmovdqa %ymm2,(%rdi) +vmovdqa %ymm4,32(%rdi) + +ret + +.macro pointwise off +#load +vmovdqa \off(%rsi),%ymm6 +vmovdqa \off+32(%rsi),%ymm8 +vmovdqa \off(%rdx),%ymm10 +vmovdqa \off+32(%rdx),%ymm12 +vpsrlq $32,%ymm6,%ymm7 +vpsrlq $32,%ymm8,%ymm9 +vmovshdup %ymm10,%ymm11 +vmovshdup %ymm12,%ymm13 + +#mul +vpmuldq %ymm6,%ymm10,%ymm6 +vpmuldq %ymm7,%ymm11,%ymm7 +vpmuldq %ymm8,%ymm12,%ymm8 +vpmuldq %ymm9,%ymm13,%ymm9 +.endm + +.macro acc +vpaddq %ymm6,%ymm2,%ymm2 +vpaddq %ymm7,%ymm3,%ymm3 +vpaddq %ymm8,%ymm4,%ymm4 +vpaddq %ymm9,%ymm5,%ymm5 +.endm + +.global cdecl(pointwise_acc_avx) +cdecl(pointwise_acc_avx): +#consts +vmovdqa _8XQINV*4(%rcx),%ymm0 +vmovdqa _8XQ*4(%rcx),%ymm1 + +xor %eax,%eax +_looptop2: +pointwise 0 + +#mov +vmovdqa %ymm6,%ymm2 +vmovdqa %ymm7,%ymm3 +vmovdqa %ymm8,%ymm4 +vmovdqa %ymm9,%ymm5 + +pointwise 1024 +acc + +#if L >= 3 +pointwise 2048 +acc +#endif + +#if L >= 4 +pointwise 3072 +acc +#endif + +#if L >= 5 +pointwise 4096 +acc +#endif + +#if L >= 6 +pointwise 5120 +acc +#endif + +#if L >= 7 +pointwise 6144 +acc +#endif + +#reduce +vpmuldq %ymm0,%ymm2,%ymm6 +vpmuldq %ymm0,%ymm3,%ymm7 +vpmuldq %ymm0,%ymm4,%ymm8 +vpmuldq %ymm0,%ymm5,%ymm9 +vpmuldq %ymm1,%ymm6,%ymm6 +vpmuldq %ymm1,%ymm7,%ymm7 +vpmuldq %ymm1,%ymm8,%ymm8 +vpmuldq %ymm1,%ymm9,%ymm9 +vpsubq %ymm6,%ymm2,%ymm2 +vpsubq %ymm7,%ymm3,%ymm3 +vpsubq %ymm8,%ymm4,%ymm4 +vpsubq %ymm9,%ymm5,%ymm5 +vpsrlq $32,%ymm2,%ymm2 +vmovshdup %ymm4,%ymm4 + +#store +vpblendd $0xAA,%ymm3,%ymm2,%ymm2 +vpblendd $0xAA,%ymm5,%ymm4,%ymm4 + +vmovdqa %ymm2,(%rdi) +vmovdqa %ymm4,32(%rdi) + +add $64,%rsi +add $64,%rdx +add $64,%rdi +add $1,%eax +cmp $16,%eax +jb _looptop2 + +ret + +.section .note.GNU-stack,"",@progbits diff --git a/avx2/poly.c b/avx2/poly.c new file mode 100644 index 0000000..340e91d --- /dev/null +++ b/avx2/poly.c @@ -0,0 +1,1128 @@ +#include +#include +#include +#include "align.h" +#include "params.h" +#include "poly.h" +#include "ntt.h" +#include "rounding.h" +#include "rejsample.h" +#include "consts.h" +#include "symmetric.h" +#include "fips202x4.h" + +#ifdef DBENCH +#include "test/cpucycles.h" +extern const uint64_t timing_overhead; +extern uint64_t *tred, *tadd, *tmul, *tround, *tsample, *tpack; +#define DBENCH_START() uint64_t time = cpucycles() +#define DBENCH_STOP(t) t += cpucycles() - time - timing_overhead +#else +#define DBENCH_START() +#define DBENCH_STOP(t) +#endif + +#define _mm256_blendv_epi32(a,b,mask) \ + _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(a), \ + _mm256_castsi256_ps(b), \ + _mm256_castsi256_ps(mask))) + +/************************************************* +* Name: poly_reduce +* +* Description: Inplace reduction of all coefficients of polynomial to +* representative in [-6283009,6283008]. Assumes input +* coefficients to be at most 2^31 - 2^22 - 1 in absolute value. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_reduce(poly *a) { + unsigned int i; + __m256i f,g; + const __m256i q = _mm256_load_si256(&qdata.vec[_8XQ/8]); + const __m256i off = _mm256_set1_epi32(1<<22); + DBENCH_START(); + + for(i = 0; i < N/8; i++) { + f = _mm256_load_si256(&a->vec[i]); + g = _mm256_add_epi32(f,off); + g = _mm256_srai_epi32(g,23); + g = _mm256_mullo_epi32(g,q); + f = _mm256_sub_epi32(f,g); + _mm256_store_si256(&a->vec[i],f); + } + + DBENCH_STOP(*tred); +} + +/************************************************* +* Name: poly_addq +* +* Description: For all coefficients of in/out polynomial add Q if +* coefficient is negative. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_caddq(poly *a) { + unsigned int i; + __m256i f,g; + const __m256i q = _mm256_load_si256(&qdata.vec[_8XQ/8]); + const __m256i zero = _mm256_setzero_si256(); + DBENCH_START(); + + for(i = 0; i < N/8; i++) { + f = _mm256_load_si256(&a->vec[i]); + g = _mm256_blendv_epi32(zero,q,f); + f = _mm256_add_epi32(f,g); + _mm256_store_si256(&a->vec[i],f); + } + + DBENCH_STOP(*tred); +} + +/************************************************* +* Name: poly_add +* +* Description: Add polynomials. No modular reduction is performed. +* +* Arguments: - poly *c: pointer to output polynomial +* - const poly *a: pointer to first summand +* - const poly *b: pointer to second summand +**************************************************/ +void poly_add(poly *c, const poly *a, const poly *b) { + unsigned int i; + __m256i f,g; + DBENCH_START(); + + for(i = 0; i < N/8; i++) { + f = _mm256_load_si256(&a->vec[i]); + g = _mm256_load_si256(&b->vec[i]); + f = _mm256_add_epi32(f,g); + _mm256_store_si256(&c->vec[i],f); + } + + DBENCH_STOP(*tadd); +} + +/************************************************* +* Name: poly_sub +* +* Description: Subtract polynomials. No modular reduction is +* performed. +* +* Arguments: - poly *c: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial to be +* subtraced from first input polynomial +**************************************************/ +void poly_sub(poly *c, const poly *a, const poly *b) { + unsigned int i; + __m256i f,g; + DBENCH_START(); + + for(i = 0; i < N/8; i++) { + f = _mm256_load_si256(&a->vec[i]); + g = _mm256_load_si256(&b->vec[i]); + f = _mm256_sub_epi32(f,g); + _mm256_store_si256(&c->vec[i],f); + } + + DBENCH_STOP(*tadd); +} + +/************************************************* +* Name: poly_shiftl +* +* Description: Multiply polynomial by 2^D without modular reduction. Assumes +* input coefficients to be less than 2^{31-D} in absolute value. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_shiftl(poly *a) { + unsigned int i; + __m256i f; + DBENCH_START(); + + for(i = 0; i < N/8; i++) { + f = _mm256_load_si256(&a->vec[i]); + f = _mm256_slli_epi32(f,D); + _mm256_store_si256(&a->vec[i],f); + } + + DBENCH_STOP(*tmul); +} + +/************************************************* +* Name: poly_ntt +* +* Description: Inplace forward NTT. Coefficients can grow by up to +* 8*Q in absolute value. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_ntt(poly *a) { + DBENCH_START(); + + ntt_avx(a->vec, qdata.vec); + + DBENCH_STOP(*tmul); +} + +/************************************************* +* Name: poly_invntt_tomont +* +* Description: Inplace inverse NTT and multiplication by 2^{32}. +* Input coefficients need to be less than Q in absolute +* value and output coefficients are again bounded by Q. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_invntt_tomont(poly *a) { + DBENCH_START(); + + invntt_avx(a->vec, qdata.vec); + + DBENCH_STOP(*tmul); +} + +void poly_nttunpack(poly *a) { + DBENCH_START(); + + nttunpack_avx(a->vec); + + DBENCH_STOP(*tmul); +} + +/************************************************* +* Name: poly_pointwise_montgomery +* +* Description: Pointwise multiplication of polynomials in NTT domain +* representation and multiplication of resulting polynomial +* by 2^{-32}. +* +* Arguments: - poly *c: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { + DBENCH_START(); + + pointwise_avx(c->vec, a->vec, b->vec, qdata.vec); + + DBENCH_STOP(*tmul); +} + +/************************************************* +* Name: poly_power2round +* +* Description: For all coefficients c of the input polynomial, +* compute c0, c1 such that c mod^+ Q = c1*2^D + c0 +* with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be +* positive standard representatives. +* +* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 +* - poly *a0: pointer to output polynomial with coefficients c0 +* - const poly *a: pointer to input polynomial +**************************************************/ +void poly_power2round(poly *a1, poly *a0, const poly *a) +{ + DBENCH_START(); + + power2round_avx(a1->vec, a0->vec, a->vec); + + DBENCH_STOP(*tround); +} + +/************************************************* +* Name: poly_decompose +* +* Description: For all coefficients c of the input polynomial, +* compute high and low bits c0, c1 such c mod^+ Q = c1*ALPHA + c0 +* with -ALPHA/2 < c0 <= ALPHA/2 except if c1 = (Q-1)/ALPHA where we +* set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0. +* Assumes coefficients to be positive standard representatives. +* +* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 +* - poly *a0: pointer to output polynomial with coefficients c0 +* - const poly *a: pointer to input polynomial +**************************************************/ +void poly_decompose(poly *a1, poly *a0, const poly *a) +{ + DBENCH_START(); + + decompose_avx(a1->vec, a0->vec, a->vec); + + DBENCH_STOP(*tround); +} + +/************************************************* +* Name: poly_make_hint +* +* Description: Compute hint array. The coefficients of which are the +* indices of the coefficients of the input polynomial +* whose low bits overflow into the high bits. +* +* Arguments: - uint8_t *h: pointer to output hint array (preallocated of length N) +* - const poly *a0: pointer to low part of input polynomial +* - const poly *a1: pointer to high part of input polynomial +* +* Returns number of hints, i.e. length of hint array. +**************************************************/ +unsigned int poly_make_hint(uint8_t hint[N], const poly *a0, const poly *a1) +{ + unsigned int r; + DBENCH_START(); + + r = make_hint_avx(hint, a0->vec, a1->vec); + + DBENCH_STOP(*tround); + return r; +} + +/************************************************* +* Name: poly_use_hint +* +* Description: Use hint polynomial to correct the high bits of a polynomial. +* +* Arguments: - poly *b: pointer to output polynomial with corrected high bits +* - const poly *a: pointer to input polynomial +* - const poly *h: pointer to input hint polynomial +**************************************************/ +void poly_use_hint(poly *b, const poly *a, const poly *h) +{ + DBENCH_START(); + + use_hint_avx(b->vec, a->vec, h->vec); + + DBENCH_STOP(*tround); +} + +/************************************************* +* Name: poly_chknorm +* +* Description: Check infinity norm of polynomial against given bound. +* Assumes input polynomial to be reduced by poly_reduce(). +* +* Arguments: - const poly *a: pointer to polynomial +* - int32_t B: norm bound +* +* Returns 0 if norm is strictly smaller than B <= (Q-1)/8 and 1 otherwise. +**************************************************/ +int poly_chknorm(const poly *a, int32_t B) { + unsigned int i; + int r; + __m256i f,t; + const __m256i bound = _mm256_set1_epi32(B-1); + DBENCH_START(); + + if(B > (Q-1)/8) + return 1; + + t = _mm256_setzero_si256(); + for(i = 0; i < N/8; i++) { + f = _mm256_load_si256(&a->vec[i]); + f = _mm256_abs_epi32(f); + f = _mm256_cmpgt_epi32(f,bound); + t = _mm256_or_si256(t,f); + } + + r = 1 - _mm256_testz_si256(t,t); + DBENCH_STOP(*tsample); + return r; +} + +/************************************************* +* Name: rej_uniform +* +* Description: Sample uniformly random coefficients in [0, Q-1] by +* performing rejection sampling on array of random bytes. +* +* Arguments: - int32_t *a: pointer to output array (allocated) +* - unsigned int len: number of coefficients to be sampled +* - const uint8_t *buf: array of random bytes +* - unsigned int buflen: length of array of random bytes +* +* Returns number of sampled coefficients. Can be smaller than len if not enough +* random bytes were given. +**************************************************/ +static unsigned int rej_uniform(int32_t *a, + unsigned int len, + const uint8_t *buf, + unsigned int buflen) +{ + unsigned int ctr, pos; + uint32_t t; + DBENCH_START(); + + ctr = pos = 0; + while(ctr < len && pos + 3 <= buflen) { + t = buf[pos++]; + t |= (uint32_t)buf[pos++] << 8; + t |= (uint32_t)buf[pos++] << 16; + t &= 0x7FFFFF; + + if(t < Q) + a[ctr++] = t; + } + + DBENCH_STOP(*tsample); + return ctr; +} + +/************************************************* +* Name: poly_uniform +* +* Description: Sample polynomial with uniformly random coefficients +* in [0,Q-1] by performing rejection sampling on the +* output stream of SHAKE256(seed|nonce) +* +* Arguments: - poly *a: pointer to output polynomial +* - const uint8_t seed[]: byte array with seed of length SEEDBYTES +* - uint16_t nonce: 2-byte nonce +**************************************************/ +void poly_uniform_preinit(poly *a, stream128_state *state) +{ + unsigned int ctr; + /* rej_uniform_avx reads up to 8 additional bytes */ + ALIGNED_UINT8(REJ_UNIFORM_BUFLEN+8) buf; + + stream128_squeezeblocks(buf.coeffs, REJ_UNIFORM_NBLOCKS, state); + ctr = rej_uniform_avx(a->coeffs, buf.coeffs); + + while(ctr < N) { + /* length of buf is always divisible by 3; hence, no bytes left */ + stream128_squeezeblocks(buf.coeffs, 1, state); + ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf.coeffs, STREAM128_BLOCKBYTES); + } +} + +void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) +{ + stream128_state state; + stream128_init(&state, seed, nonce); + poly_uniform_preinit(a, &state); +} + +void poly_uniform_4x(poly *a0, + poly *a1, + poly *a2, + poly *a3, + const uint8_t seed[32], + uint16_t nonce0, + uint16_t nonce1, + uint16_t nonce2, + uint16_t nonce3) +{ + unsigned int ctr0, ctr1, ctr2, ctr3; + ALIGNED_UINT8(REJ_UNIFORM_BUFLEN+8) buf[4]; + keccakx4_state state; + __m256i f; + + f = _mm256_loadu_si256((__m256i *)seed); + _mm256_store_si256(buf[0].vec,f); + _mm256_store_si256(buf[1].vec,f); + _mm256_store_si256(buf[2].vec,f); + _mm256_store_si256(buf[3].vec,f); + + buf[0].coeffs[SEEDBYTES+0] = nonce0; + buf[0].coeffs[SEEDBYTES+1] = nonce0 >> 8; + buf[1].coeffs[SEEDBYTES+0] = nonce1; + buf[1].coeffs[SEEDBYTES+1] = nonce1 >> 8; + buf[2].coeffs[SEEDBYTES+0] = nonce2; + buf[2].coeffs[SEEDBYTES+1] = nonce2 >> 8; + buf[3].coeffs[SEEDBYTES+0] = nonce3; + buf[3].coeffs[SEEDBYTES+1] = nonce3 >> 8; + + shake128x4_absorb_once(&state, buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, SEEDBYTES + 2); + shake128x4_squeezeblocks(buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, REJ_UNIFORM_NBLOCKS, &state); + + ctr0 = rej_uniform_avx(a0->coeffs, buf[0].coeffs); + ctr1 = rej_uniform_avx(a1->coeffs, buf[1].coeffs); + ctr2 = rej_uniform_avx(a2->coeffs, buf[2].coeffs); + ctr3 = rej_uniform_avx(a3->coeffs, buf[3].coeffs); + + while(ctr0 < N || ctr1 < N || ctr2 < N || ctr3 < N) { + shake128x4_squeezeblocks(buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, 1, &state); + + ctr0 += rej_uniform(a0->coeffs + ctr0, N - ctr0, buf[0].coeffs, SHAKE128_RATE); + ctr1 += rej_uniform(a1->coeffs + ctr1, N - ctr1, buf[1].coeffs, SHAKE128_RATE); + ctr2 += rej_uniform(a2->coeffs + ctr2, N - ctr2, buf[2].coeffs, SHAKE128_RATE); + ctr3 += rej_uniform(a3->coeffs + ctr3, N - ctr3, buf[3].coeffs, SHAKE128_RATE); + } +} + +/************************************************* +* Name: rej_eta +* +* Description: Sample uniformly random coefficients in [-ETA, ETA] by +* performing rejection sampling on array of random bytes. +* +* Arguments: - int32_t *a: pointer to output array (allocated) +* - unsigned int len: number of coefficients to be sampled +* - const uint8_t *buf: array of random bytes +* - unsigned int buflen: length of array of random bytes +* +* Returns number of sampled coefficients. Can be smaller than len if not enough +* random bytes were given. +**************************************************/ +static unsigned int rej_eta(int32_t *a, + unsigned int len, + const uint8_t *buf, + unsigned int buflen) +{ + unsigned int ctr, pos; + uint32_t t0, t1; + DBENCH_START(); + + ctr = pos = 0; + while(ctr < len && pos < buflen) { + t0 = buf[pos] & 0x0F; + t1 = buf[pos++] >> 4; + +#if ETA == 2 + if(t0 < 15) { + t0 = t0 - (205*t0 >> 10)*5; + a[ctr++] = 2 - t0; + } + if(t1 < 15 && ctr < len) { + t1 = t1 - (205*t1 >> 10)*5; + a[ctr++] = 2 - t1; + } +#elif ETA == 4 + if(t0 < 9) + a[ctr++] = 4 - t0; + if(t1 < 9 && ctr < len) + a[ctr++] = 4 - t1; +#endif + } + + DBENCH_STOP(*tsample); + return ctr; +} + +/************************************************* +* Name: poly_uniform_eta +* +* Description: Sample polynomial with uniformly random coefficients +* in [-ETA,ETA] by performing rejection sampling using the +* output stream of SHAKE256(seed|nonce) +* +* Arguments: - poly *a: pointer to output polynomial +* - const uint8_t seed[]: byte array with seed of length CRHBYTES +* - uint16_t nonce: 2-byte nonce +**************************************************/ +void poly_uniform_eta_preinit(poly *a, stream256_state *state) +{ + unsigned int ctr; + ALIGNED_UINT8(REJ_UNIFORM_ETA_BUFLEN) buf; + + stream256_squeezeblocks(buf.coeffs, REJ_UNIFORM_ETA_NBLOCKS, state); + ctr = rej_eta_avx(a->coeffs, buf.coeffs); + + while(ctr < N) { + stream256_squeezeblocks(buf.coeffs, 1, state); + ctr += rej_eta(a->coeffs + ctr, N - ctr, buf.coeffs, STREAM256_BLOCKBYTES); + } +} + +void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) +{ + stream256_state state; + stream256_init(&state, seed, nonce); + poly_uniform_eta_preinit(a, &state); +} + +void poly_uniform_eta_4x(poly *a0, + poly *a1, + poly *a2, + poly *a3, + const uint8_t seed[64], + uint16_t nonce0, + uint16_t nonce1, + uint16_t nonce2, + uint16_t nonce3) +{ + unsigned int ctr0, ctr1, ctr2, ctr3; + ALIGNED_UINT8(REJ_UNIFORM_ETA_BUFLEN) buf[4]; + + __m256i f; + keccakx4_state state; + + f = _mm256_loadu_si256((__m256i *)&seed[0]); + _mm256_store_si256(&buf[0].vec[0],f); + _mm256_store_si256(&buf[1].vec[0],f); + _mm256_store_si256(&buf[2].vec[0],f); + _mm256_store_si256(&buf[3].vec[0],f); + f = _mm256_loadu_si256((__m256i *)&seed[32]); + _mm256_store_si256(&buf[0].vec[1],f); + _mm256_store_si256(&buf[1].vec[1],f); + _mm256_store_si256(&buf[2].vec[1],f); + _mm256_store_si256(&buf[3].vec[1],f); + + buf[0].coeffs[64] = nonce0; + buf[0].coeffs[65] = nonce0 >> 8; + buf[1].coeffs[64] = nonce1; + buf[1].coeffs[65] = nonce1 >> 8; + buf[2].coeffs[64] = nonce2; + buf[2].coeffs[65] = nonce2 >> 8; + buf[3].coeffs[64] = nonce3; + buf[3].coeffs[65] = nonce3 >> 8; + + shake256x4_absorb_once(&state, buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, 66); + shake256x4_squeezeblocks(buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, REJ_UNIFORM_ETA_NBLOCKS, &state); + + ctr0 = rej_eta_avx(a0->coeffs, buf[0].coeffs); + ctr1 = rej_eta_avx(a1->coeffs, buf[1].coeffs); + ctr2 = rej_eta_avx(a2->coeffs, buf[2].coeffs); + ctr3 = rej_eta_avx(a3->coeffs, buf[3].coeffs); + + while(ctr0 < N || ctr1 < N || ctr2 < N || ctr3 < N) { + shake256x4_squeezeblocks(buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, 1, &state); + + ctr0 += rej_eta(a0->coeffs + ctr0, N - ctr0, buf[0].coeffs, SHAKE256_RATE); + ctr1 += rej_eta(a1->coeffs + ctr1, N - ctr1, buf[1].coeffs, SHAKE256_RATE); + ctr2 += rej_eta(a2->coeffs + ctr2, N - ctr2, buf[2].coeffs, SHAKE256_RATE); + ctr3 += rej_eta(a3->coeffs + ctr3, N - ctr3, buf[3].coeffs, SHAKE256_RATE); + } +} + +/************************************************* +* Name: poly_uniform_gamma1 +* +* Description: Sample polynomial with uniformly random coefficients +* in [-(GAMMA1 - 1), GAMMA1] by unpacking output stream +* of SHAKE256(seed|nonce) +* +* Arguments: - poly *a: pointer to output polynomial +* - const uint8_t seed[]: byte array with seed of length CRHBYTES +* - uint16_t nonce: 16-bit nonce +**************************************************/ +#define POLY_UNIFORM_GAMMA1_NBLOCKS ((POLYZ_PACKEDBYTES+STREAM256_BLOCKBYTES-1)/STREAM256_BLOCKBYTES) +void poly_uniform_gamma1_preinit(poly *a, stream256_state *state) +{ + /* polyz_unpack reads 14 additional bytes */ + ALIGNED_UINT8(POLY_UNIFORM_GAMMA1_NBLOCKS*STREAM256_BLOCKBYTES+14) buf; + stream256_squeezeblocks(buf.coeffs, POLY_UNIFORM_GAMMA1_NBLOCKS, state); + polyz_unpack(a, buf.coeffs); +} + +void poly_uniform_gamma1(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) +{ + stream256_state state; + stream256_init(&state, seed, nonce); + poly_uniform_gamma1_preinit(a, &state); +} + +void poly_uniform_gamma1_4x(poly *a0, + poly *a1, + poly *a2, + poly *a3, + const uint8_t seed[64], + uint16_t nonce0, + uint16_t nonce1, + uint16_t nonce2, + uint16_t nonce3) +{ + ALIGNED_UINT8(POLY_UNIFORM_GAMMA1_NBLOCKS*STREAM256_BLOCKBYTES+14) buf[4]; + keccakx4_state state; + __m256i f; + + f = _mm256_loadu_si256((__m256i *)&seed[0]); + _mm256_store_si256(&buf[0].vec[0],f); + _mm256_store_si256(&buf[1].vec[0],f); + _mm256_store_si256(&buf[2].vec[0],f); + _mm256_store_si256(&buf[3].vec[0],f); + f = _mm256_loadu_si256((__m256i *)&seed[32]); + _mm256_store_si256(&buf[0].vec[1],f); + _mm256_store_si256(&buf[1].vec[1],f); + _mm256_store_si256(&buf[2].vec[1],f); + _mm256_store_si256(&buf[3].vec[1],f); + + buf[0].coeffs[64] = nonce0; + buf[0].coeffs[65] = nonce0 >> 8; + buf[1].coeffs[64] = nonce1; + buf[1].coeffs[65] = nonce1 >> 8; + buf[2].coeffs[64] = nonce2; + buf[2].coeffs[65] = nonce2 >> 8; + buf[3].coeffs[64] = nonce3; + buf[3].coeffs[65] = nonce3 >> 8; + + shake256x4_absorb_once(&state, buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, 66); + shake256x4_squeezeblocks(buf[0].coeffs, buf[1].coeffs, buf[2].coeffs, buf[3].coeffs, POLY_UNIFORM_GAMMA1_NBLOCKS, &state); + + polyz_unpack(a0, buf[0].coeffs); + polyz_unpack(a1, buf[1].coeffs); + polyz_unpack(a2, buf[2].coeffs); + polyz_unpack(a3, buf[3].coeffs); +} + +/************************************************* +* Name: challenge +* +* Description: Implementation of H. Samples polynomial with TAU nonzero +* coefficients in {-1,1} using the output stream of +* SHAKE256(seed). +* +* Arguments: - poly *c: pointer to output polynomial +* - const uint8_t mu[]: byte array containing seed of length CTILDEBYTES +**************************************************/ +void poly_challenge(poly * restrict c, const uint8_t seed[CTILDEBYTES]) { + unsigned int i, b, pos; + uint64_t signs; + ALIGNED_UINT8(SHAKE256_RATE) buf; + keccak_state state; + + shake256_init(&state); + shake256_absorb(&state, seed, CTILDEBYTES); + shake256_finalize(&state); + shake256_squeezeblocks(buf.coeffs, 1, &state); + + memcpy(&signs, buf.coeffs, 8); + pos = 8; + + memset(c->vec, 0, sizeof(poly)); + for(i = N-TAU; i < N; ++i) { + do { + if(pos >= SHAKE256_RATE) { + shake256_squeezeblocks(buf.coeffs, 1, &state); + pos = 0; + } + + b = buf.coeffs[pos++]; + } while(b > i); + + c->coeffs[i] = c->coeffs[b]; + c->coeffs[b] = 1 - 2*(signs & 1); + signs >>= 1; + } +} + +/************************************************* +* Name: polyeta_pack +* +* Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYETA_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyeta_pack(uint8_t r[POLYETA_PACKEDBYTES], const poly * restrict a) { + unsigned int i; + uint8_t t[8]; + DBENCH_START(); + +#if ETA == 2 + for(i = 0; i < N/8; ++i) { + t[0] = ETA - a->coeffs[8*i+0]; + t[1] = ETA - a->coeffs[8*i+1]; + t[2] = ETA - a->coeffs[8*i+2]; + t[3] = ETA - a->coeffs[8*i+3]; + t[4] = ETA - a->coeffs[8*i+4]; + t[5] = ETA - a->coeffs[8*i+5]; + t[6] = ETA - a->coeffs[8*i+6]; + t[7] = ETA - a->coeffs[8*i+7]; + + r[3*i+0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); + r[3*i+1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); + r[3*i+2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + } +#elif ETA == 4 + for(i = 0; i < N/2; ++i) { + t[0] = ETA - a->coeffs[2*i+0]; + t[1] = ETA - a->coeffs[2*i+1]; + r[i] = t[0] | (t[1] << 4); + } +#endif + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyeta_unpack +* +* Description: Unpack polynomial with coefficients in [-ETA,ETA]. +* +* Arguments: - poly *r: pointer to output polynomial +* - const uint8_t *a: byte array with bit-packed polynomial +**************************************************/ +void polyeta_unpack(poly * restrict r, const uint8_t a[POLYETA_PACKEDBYTES]) { + unsigned int i; + DBENCH_START(); + +#if ETA == 2 + for(i = 0; i < N/8; ++i) { + r->coeffs[8*i+0] = (a[3*i+0] >> 0) & 7; + r->coeffs[8*i+1] = (a[3*i+0] >> 3) & 7; + r->coeffs[8*i+2] = ((a[3*i+0] >> 6) | (a[3*i+1] << 2)) & 7; + r->coeffs[8*i+3] = (a[3*i+1] >> 1) & 7; + r->coeffs[8*i+4] = (a[3*i+1] >> 4) & 7; + r->coeffs[8*i+5] = ((a[3*i+1] >> 7) | (a[3*i+2] << 1)) & 7; + r->coeffs[8*i+6] = (a[3*i+2] >> 2) & 7; + r->coeffs[8*i+7] = (a[3*i+2] >> 5) & 7; + + r->coeffs[8*i+0] = ETA - r->coeffs[8*i+0]; + r->coeffs[8*i+1] = ETA - r->coeffs[8*i+1]; + r->coeffs[8*i+2] = ETA - r->coeffs[8*i+2]; + r->coeffs[8*i+3] = ETA - r->coeffs[8*i+3]; + r->coeffs[8*i+4] = ETA - r->coeffs[8*i+4]; + r->coeffs[8*i+5] = ETA - r->coeffs[8*i+5]; + r->coeffs[8*i+6] = ETA - r->coeffs[8*i+6]; + r->coeffs[8*i+7] = ETA - r->coeffs[8*i+7]; + } +#elif ETA == 4 + for(i = 0; i < N/2; ++i) { + r->coeffs[2*i+0] = a[i] & 0x0F; + r->coeffs[2*i+1] = a[i] >> 4; + r->coeffs[2*i+0] = ETA - r->coeffs[2*i+0]; + r->coeffs[2*i+1] = ETA - r->coeffs[2*i+1]; + } +#endif + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyt1_pack +* +* Description: Bit-pack polynomial t1 with coefficients fitting in 10 bits. +* Input coefficients are assumed to be positive standard representatives. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYT1_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyt1_pack(uint8_t r[POLYT1_PACKEDBYTES], const poly * restrict a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N/4; ++i) { + r[5*i+0] = (a->coeffs[4*i+0] >> 0); + r[5*i+1] = (a->coeffs[4*i+0] >> 8) | (a->coeffs[4*i+1] << 2); + r[5*i+2] = (a->coeffs[4*i+1] >> 6) | (a->coeffs[4*i+2] << 4); + r[5*i+3] = (a->coeffs[4*i+2] >> 4) | (a->coeffs[4*i+3] << 6); + r[5*i+4] = (a->coeffs[4*i+3] >> 2); + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyt1_unpack +* +* Description: Unpack polynomial t1 with 10-bit coefficients. +* Output coefficients are positive standard representatives. +* +* Arguments: - poly *r: pointer to output polynomial +* - const uint8_t *a: byte array with bit-packed polynomial +**************************************************/ +void polyt1_unpack(poly * restrict r, const uint8_t a[POLYT1_PACKEDBYTES]) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N/4; ++i) { + r->coeffs[4*i+0] = ((a[5*i+0] >> 0) | ((uint32_t)a[5*i+1] << 8)) & 0x3FF; + r->coeffs[4*i+1] = ((a[5*i+1] >> 2) | ((uint32_t)a[5*i+2] << 6)) & 0x3FF; + r->coeffs[4*i+2] = ((a[5*i+2] >> 4) | ((uint32_t)a[5*i+3] << 4)) & 0x3FF; + r->coeffs[4*i+3] = ((a[5*i+3] >> 6) | ((uint32_t)a[5*i+4] << 2)) & 0x3FF; + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyt0_pack +* +* Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYT0_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyt0_pack(uint8_t r[POLYT0_PACKEDBYTES], const poly * restrict a) { + unsigned int i; + uint32_t t[8]; + DBENCH_START(); + + for(i = 0; i < N/8; ++i) { + t[0] = (1 << (D-1)) - a->coeffs[8*i+0]; + t[1] = (1 << (D-1)) - a->coeffs[8*i+1]; + t[2] = (1 << (D-1)) - a->coeffs[8*i+2]; + t[3] = (1 << (D-1)) - a->coeffs[8*i+3]; + t[4] = (1 << (D-1)) - a->coeffs[8*i+4]; + t[5] = (1 << (D-1)) - a->coeffs[8*i+5]; + t[6] = (1 << (D-1)) - a->coeffs[8*i+6]; + t[7] = (1 << (D-1)) - a->coeffs[8*i+7]; + + r[13*i+ 0] = t[0]; + r[13*i+ 1] = t[0] >> 8; + r[13*i+ 1] |= t[1] << 5; + r[13*i+ 2] = t[1] >> 3; + r[13*i+ 3] = t[1] >> 11; + r[13*i+ 3] |= t[2] << 2; + r[13*i+ 4] = t[2] >> 6; + r[13*i+ 4] |= t[3] << 7; + r[13*i+ 5] = t[3] >> 1; + r[13*i+ 6] = t[3] >> 9; + r[13*i+ 6] |= t[4] << 4; + r[13*i+ 7] = t[4] >> 4; + r[13*i+ 8] = t[4] >> 12; + r[13*i+ 8] |= t[5] << 1; + r[13*i+ 9] = t[5] >> 7; + r[13*i+ 9] |= t[6] << 6; + r[13*i+10] = t[6] >> 2; + r[13*i+11] = t[6] >> 10; + r[13*i+11] |= t[7] << 3; + r[13*i+12] = t[7] >> 5; + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyt0_unpack +* +* Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. +* +* Arguments: - poly *r: pointer to output polynomial +* - const uint8_t *a: byte array with bit-packed polynomial +**************************************************/ +void polyt0_unpack(poly * restrict r, const uint8_t a[POLYT0_PACKEDBYTES]) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N/8; ++i) { + r->coeffs[8*i+0] = a[13*i+0]; + r->coeffs[8*i+0] |= (uint32_t)a[13*i+1] << 8; + r->coeffs[8*i+0] &= 0x1FFF; + + r->coeffs[8*i+1] = a[13*i+1] >> 5; + r->coeffs[8*i+1] |= (uint32_t)a[13*i+2] << 3; + r->coeffs[8*i+1] |= (uint32_t)a[13*i+3] << 11; + r->coeffs[8*i+1] &= 0x1FFF; + + r->coeffs[8*i+2] = a[13*i+3] >> 2; + r->coeffs[8*i+2] |= (uint32_t)a[13*i+4] << 6; + r->coeffs[8*i+2] &= 0x1FFF; + + r->coeffs[8*i+3] = a[13*i+4] >> 7; + r->coeffs[8*i+3] |= (uint32_t)a[13*i+5] << 1; + r->coeffs[8*i+3] |= (uint32_t)a[13*i+6] << 9; + r->coeffs[8*i+3] &= 0x1FFF; + + r->coeffs[8*i+4] = a[13*i+6] >> 4; + r->coeffs[8*i+4] |= (uint32_t)a[13*i+7] << 4; + r->coeffs[8*i+4] |= (uint32_t)a[13*i+8] << 12; + r->coeffs[8*i+4] &= 0x1FFF; + + r->coeffs[8*i+5] = a[13*i+8] >> 1; + r->coeffs[8*i+5] |= (uint32_t)a[13*i+9] << 7; + r->coeffs[8*i+5] &= 0x1FFF; + + r->coeffs[8*i+6] = a[13*i+9] >> 6; + r->coeffs[8*i+6] |= (uint32_t)a[13*i+10] << 2; + r->coeffs[8*i+6] |= (uint32_t)a[13*i+11] << 10; + r->coeffs[8*i+6] &= 0x1FFF; + + r->coeffs[8*i+7] = a[13*i+11] >> 3; + r->coeffs[8*i+7] |= (uint32_t)a[13*i+12] << 5; + r->coeffs[8*i+7] &= 0x1FFF; + + r->coeffs[8*i+0] = (1 << (D-1)) - r->coeffs[8*i+0]; + r->coeffs[8*i+1] = (1 << (D-1)) - r->coeffs[8*i+1]; + r->coeffs[8*i+2] = (1 << (D-1)) - r->coeffs[8*i+2]; + r->coeffs[8*i+3] = (1 << (D-1)) - r->coeffs[8*i+3]; + r->coeffs[8*i+4] = (1 << (D-1)) - r->coeffs[8*i+4]; + r->coeffs[8*i+5] = (1 << (D-1)) - r->coeffs[8*i+5]; + r->coeffs[8*i+6] = (1 << (D-1)) - r->coeffs[8*i+6]; + r->coeffs[8*i+7] = (1 << (D-1)) - r->coeffs[8*i+7]; + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyz_pack +* +* Description: Bit-pack polynomial with coefficients +* in [-(GAMMA1 - 1), GAMMA1]. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYZ_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyz_pack(uint8_t r[POLYZ_PACKEDBYTES], const poly * restrict a) { + unsigned int i; + uint32_t t[4]; + DBENCH_START(); + +#if GAMMA1 == (1 << 17) + for(i = 0; i < N/4; ++i) { + t[0] = GAMMA1 - a->coeffs[4*i+0]; + t[1] = GAMMA1 - a->coeffs[4*i+1]; + t[2] = GAMMA1 - a->coeffs[4*i+2]; + t[3] = GAMMA1 - a->coeffs[4*i+3]; + + r[9*i+0] = t[0]; + r[9*i+1] = t[0] >> 8; + r[9*i+2] = t[0] >> 16; + r[9*i+2] |= t[1] << 2; + r[9*i+3] = t[1] >> 6; + r[9*i+4] = t[1] >> 14; + r[9*i+4] |= t[2] << 4; + r[9*i+5] = t[2] >> 4; + r[9*i+6] = t[2] >> 12; + r[9*i+6] |= t[3] << 6; + r[9*i+7] = t[3] >> 2; + r[9*i+8] = t[3] >> 10; + } +#elif GAMMA1 == (1 << 19) + for(i = 0; i < N/2; ++i) { + t[0] = GAMMA1 - a->coeffs[2*i+0]; + t[1] = GAMMA1 - a->coeffs[2*i+1]; + + r[5*i+0] = t[0]; + r[5*i+1] = t[0] >> 8; + r[5*i+2] = t[0] >> 16; + r[5*i+2] |= t[1] << 4; + r[5*i+3] = t[1] >> 4; + r[5*i+4] = t[1] >> 12; + } +#endif + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyz_unpack +* +* Description: Unpack polynomial z with coefficients +* in [-(GAMMA1 - 1), GAMMA1]. +* +* Arguments: - poly *r: pointer to output polynomial +* - const uint8_t *a: byte array with bit-packed polynomial +**************************************************/ +#if GAMMA1 == (1 << 17) +void polyz_unpack(poly * restrict r, const uint8_t *a) { + unsigned int i; + __m256i f; + const __m256i shufbidx = _mm256_set_epi8(-1, 9, 8, 7,-1, 7, 6, 5,-1, 5, 4, 3,-1, 3, 2, 1, + -1, 8, 7, 6,-1, 6, 5, 4,-1, 4, 3, 2,-1, 2, 1, 0); + const __m256i srlvdidx = _mm256_set_epi32(6,4,2,0,6,4,2,0); + const __m256i mask = _mm256_set1_epi32(0x3FFFF); + const __m256i gamma1 = _mm256_set1_epi32(GAMMA1); + DBENCH_START(); + + for(i = 0; i < N/8; i++) { + f = _mm256_loadu_si256((__m256i *)&a[18*i]); + f = _mm256_permute4x64_epi64(f,0x94); + f = _mm256_shuffle_epi8(f,shufbidx); + f = _mm256_srlv_epi32(f,srlvdidx); + f = _mm256_and_si256(f,mask); + f = _mm256_sub_epi32(gamma1,f); + _mm256_store_si256(&r->vec[i],f); + } + + DBENCH_STOP(*tpack); +} + +#elif GAMMA1 == (1 << 19) +void polyz_unpack(poly * restrict r, const uint8_t *a) { + unsigned int i; + __m256i f; + const __m256i shufbidx = _mm256_set_epi8(-1,11,10, 9,-1, 9, 8, 7,-1, 6, 5, 4,-1, 4, 3, 2, + -1, 9, 8, 7,-1, 7, 6, 5,-1, 4, 3, 2,-1, 2, 1, 0); + const __m256i srlvdidx = _mm256_set1_epi64x((uint64_t)4 << 32); + const __m256i mask = _mm256_set1_epi32(0xFFFFF); + const __m256i gamma1 = _mm256_set1_epi32(GAMMA1); + DBENCH_START(); + + for(i = 0; i < N/8; i++) { + f = _mm256_loadu_si256((__m256i *)&a[20*i]); + f = _mm256_permute4x64_epi64(f,0x94); + f = _mm256_shuffle_epi8(f,shufbidx); + f = _mm256_srlv_epi32(f,srlvdidx); + f = _mm256_and_si256(f,mask); + f = _mm256_sub_epi32(gamma1,f); + _mm256_store_si256(&r->vec[i],f); + } + + DBENCH_STOP(*tpack); +} +#endif + +/************************************************* +* Name: polyw1_pack +* +* Description: Bit-pack polynomial w1 with coefficients in [0,15] or [0,43]. +* Input coefficients are assumed to be positive standard representatives. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYW1_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +#if GAMMA2 == (Q-1)/88 +void polyw1_pack(uint8_t *r, const poly * restrict a) { + unsigned int i; + __m256i f0,f1,f2,f3; + const __m256i shift1 = _mm256_set1_epi16((64 << 8) + 1); + const __m256i shift2 = _mm256_set1_epi32((4096 << 16) + 1); + const __m256i shufdidx1 = _mm256_set_epi32(7,3,6,2,5,1,4,0); + const __m256i shufdidx2 = _mm256_set_epi32(-1,-1,6,5,4,2,1,0); + const __m256i shufbidx = _mm256_set_epi8(-1,-1,-1,-1,14,13,12,10, 9, 8, 6, 5, 4, 2, 1, 0, + -1,-1,-1,-1,14,13,12,10, 9, 8, 6, 5, 4, 2, 1, 0); + DBENCH_START(); + + for(i = 0; i < N/32; i++) { + f0 = _mm256_load_si256(&a->vec[4*i+0]); + f1 = _mm256_load_si256(&a->vec[4*i+1]); + f2 = _mm256_load_si256(&a->vec[4*i+2]); + f3 = _mm256_load_si256(&a->vec[4*i+3]); + f0 = _mm256_packus_epi32(f0,f1); + f1 = _mm256_packus_epi32(f2,f3); + f0 = _mm256_packus_epi16(f0,f1); + f0 = _mm256_maddubs_epi16(f0,shift1); + f0 = _mm256_madd_epi16(f0,shift2); + f0 = _mm256_permutevar8x32_epi32(f0,shufdidx1); + f0 = _mm256_shuffle_epi8(f0,shufbidx); + f0 = _mm256_permutevar8x32_epi32(f0,shufdidx2); + _mm256_storeu_si256((__m256i *)&r[24*i],f0); + } + + DBENCH_STOP(*tpack); +} + +#elif GAMMA2 == (Q-1)/32 +void polyw1_pack(uint8_t *r, const poly * restrict a) { + unsigned int i; + __m256i f0, f1, f2, f3, f4, f5, f6, f7; + const __m256i shift = _mm256_set1_epi16((16 << 8) + 1); + const __m256i shufbidx = _mm256_set_epi8(15,14, 7, 6,13,12, 5, 4,11,10, 3, 2, 9, 8, 1, 0, + 15,14, 7, 6,13,12, 5, 4,11,10, 3, 2, 9, 8, 1, 0); + DBENCH_START(); + + for(i = 0; i < N/64; ++i) { + f0 = _mm256_load_si256(&a->vec[8*i+0]); + f1 = _mm256_load_si256(&a->vec[8*i+1]); + f2 = _mm256_load_si256(&a->vec[8*i+2]); + f3 = _mm256_load_si256(&a->vec[8*i+3]); + f4 = _mm256_load_si256(&a->vec[8*i+4]); + f5 = _mm256_load_si256(&a->vec[8*i+5]); + f6 = _mm256_load_si256(&a->vec[8*i+6]); + f7 = _mm256_load_si256(&a->vec[8*i+7]); + f0 = _mm256_packus_epi32(f0,f1); + f1 = _mm256_packus_epi32(f2,f3); + f2 = _mm256_packus_epi32(f4,f5); + f3 = _mm256_packus_epi32(f6,f7); + f0 = _mm256_packus_epi16(f0,f1); + f1 = _mm256_packus_epi16(f2,f3); + f0 = _mm256_maddubs_epi16(f0,shift); + f1 = _mm256_maddubs_epi16(f1,shift); + f0 = _mm256_packus_epi16(f0,f1); + f0 = _mm256_permute4x64_epi64(f0,0xD8); + f0 = _mm256_shuffle_epi8(f0,shufbidx); + _mm256_storeu_si256((__m256i *)&r[32*i], f0); + } + + DBENCH_STOP(*tpack); +} +#endif diff --git a/avx2/poly.h b/avx2/poly.h new file mode 100644 index 0000000..7d93088 --- /dev/null +++ b/avx2/poly.h @@ -0,0 +1,112 @@ +#ifndef POLY_H +#define POLY_H + +#include +#include "align.h" +#include "params.h" +#include "symmetric.h" + +typedef ALIGNED_INT32(N) poly; + +#define poly_reduce DILITHIUM_NAMESPACE(poly_reduce) +void poly_reduce(poly *a); +#define poly_caddq DILITHIUM_NAMESPACE(poly_caddq) +void poly_caddq(poly *a); + +#define poly_add DILITHIUM_NAMESPACE(poly_add) +void poly_add(poly *c, const poly *a, const poly *b); +#define poly_sub DILITHIUM_NAMESPACE(poly_sub) +void poly_sub(poly *c, const poly *a, const poly *b); +#define poly_shiftl DILITHIUM_NAMESPACE(poly_shiftl) +void poly_shiftl(poly *a); + +#define poly_ntt DILITHIUM_NAMESPACE(poly_ntt) +void poly_ntt(poly *a); +#define poly_invntt_tomont DILITHIUM_NAMESPACE(poly_invntt_tomont) +void poly_invntt_tomont(poly *a); +#define poly_nttunpack DILITHIUM_NAMESPACE(poly_nttunpack) +void poly_nttunpack(poly *a); +#define poly_pointwise_montgomery DILITHIUM_NAMESPACE(poly_pointwise_montgomery) +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); + +#define poly_power2round DILITHIUM_NAMESPACE(poly_power2round) +void poly_power2round(poly *a1, poly *a0, const poly *a); +#define poly_decompose DILITHIUM_NAMESPACE(poly_decompose) +void poly_decompose(poly *a1, poly *a0, const poly *a); +#define poly_make_hint DILITHIUM_NAMESPACE(poly_make_hint) +unsigned int poly_make_hint(uint8_t hint[N], const poly *a0, const poly *a1); +#define poly_use_hint DILITHIUM_NAMESPACE(poly_use_hint) +void poly_use_hint(poly *b, const poly *a, const poly *h); + +#define poly_chknorm DILITHIUM_NAMESPACE(poly_chknorm) +int poly_chknorm(const poly *a, int32_t B); +#define poly_uniform_preinit DILITHIUM_NAMESPACE(poly_uniform_preinit) +void poly_uniform_preinit(poly *a, stream128_state *state); +#define poly_uniform DILITHIUM_NAMESPACE(poly_uniform) +void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); +#define poly_uniform_eta_preinit DILITHIUM_NAMESPACE(poly_uniform_eta_preinit) +void poly_uniform_eta_preinit(poly *a, stream256_state *state); +#define poly_uniform_eta DILITHIUM_NAMESPACE(poly_uniform_eta) +void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); +#define poly_uniform_gamma1_preinit DILITHIUM_NAMESPACE(poly_uniform_gamma1_preinit) +void poly_uniform_gamma1_preinit(poly *a, stream256_state *state); +#define poly_uniform_gamma1 DILITHIUM_NAMESPACE(poly_uniform_gamma1) +void poly_uniform_gamma1(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); +#define poly_challenge DILITHIUM_NAMESPACE(poly_challenge) +void poly_challenge(poly *c, const uint8_t seed[CTILDEBYTES]); + +#define poly_uniform_4x DILITHIUM_NAMESPACE(poly_uniform_4x) +void poly_uniform_4x(poly *a0, + poly *a1, + poly *a2, + poly *a3, + const uint8_t seed[SEEDBYTES], + uint16_t nonce0, + uint16_t nonce1, + uint16_t nonce2, + uint16_t nonce3); +#define poly_uniform_eta_4x DILITHIUM_NAMESPACE(poly_uniform_eta_4x) +void poly_uniform_eta_4x(poly *a0, + poly *a1, + poly *a2, + poly *a3, + const uint8_t seed[CRHBYTES], + uint16_t nonce0, + uint16_t nonce1, + uint16_t nonce2, + uint16_t nonce3); +#define poly_uniform_gamma1_4x DILITHIUM_NAMESPACE(poly_uniform_gamma1_4x) +void poly_uniform_gamma1_4x(poly *a0, + poly *a1, + poly *a2, + poly *a3, + const uint8_t seed[CRHBYTES], + uint16_t nonce0, + uint16_t nonce1, + uint16_t nonce2, + uint16_t nonce3); + +#define polyeta_pack DILITHIUM_NAMESPACE(polyeta_pack) +void polyeta_pack(uint8_t r[POLYETA_PACKEDBYTES], const poly *a); +#define polyeta_unpack DILITHIUM_NAMESPACE(polyeta_unpack) +void polyeta_unpack(poly *r, const uint8_t a[POLYETA_PACKEDBYTES]); + +#define polyt1_pack DILITHIUM_NAMESPACE(polyt1_pack) +void polyt1_pack(uint8_t r[POLYT1_PACKEDBYTES], const poly *a); +#define polyt1_unpack DILITHIUM_NAMESPACE(polyt1_unpack) +void polyt1_unpack(poly *r, const uint8_t a[POLYT1_PACKEDBYTES]); + +#define polyt0_pack DILITHIUM_NAMESPACE(polyt0_pack) +void polyt0_pack(uint8_t r[POLYT0_PACKEDBYTES], const poly *a); +#define polyt0_unpack DILITHIUM_NAMESPACE(polyt0_unpack) +void polyt0_unpack(poly *r, const uint8_t a[POLYT0_PACKEDBYTES]); + +#define polyz_pack DILITHIUM_NAMESPACE(polyz_pack) +void polyz_pack(uint8_t r[POLYZ_PACKEDBYTES], const poly *a); +#define polyz_unpack DILITHIUM_NAMESPACE(polyz_unpack) +void polyz_unpack(poly *r, const uint8_t *a); + +#define polyw1_pack DILITHIUM_NAMESPACE(polyw1_pack) +void polyw1_pack(uint8_t *r, const poly *a); + +#endif diff --git a/avx2/polyvec.c b/avx2/polyvec.c new file mode 100644 index 0000000..0db3514 --- /dev/null +++ b/avx2/polyvec.c @@ -0,0 +1,588 @@ +#include +#include "params.h" +#include "polyvec.h" +#include "poly.h" +#include "ntt.h" +#include "consts.h" + +/************************************************* +* Name: expand_mat +* +* Description: Implementation of ExpandA. Generates matrix A with uniformly +* random coefficients a_{i,j} by performing rejection +* sampling on the output stream of SHAKE128(rho|j|i) +* +* Arguments: - polyvecl mat[K]: output matrix +* - const uint8_t rho[]: byte array containing seed rho +**************************************************/ + +#if K == 4 && L == 4 +void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { + polyvec_matrix_expand_row0(&mat[0], NULL, rho); + polyvec_matrix_expand_row1(&mat[1], NULL, rho); + polyvec_matrix_expand_row2(&mat[2], NULL, rho); + polyvec_matrix_expand_row3(&mat[3], NULL, rho); +} + +void polyvec_matrix_expand_row0(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 0, 1, 2, 3); + poly_nttunpack(&rowa->vec[0]); + poly_nttunpack(&rowa->vec[1]); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); +} + +void polyvec_matrix_expand_row1(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 256, 257, 258, 259); + poly_nttunpack(&rowa->vec[0]); + poly_nttunpack(&rowa->vec[1]); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); +} + +void polyvec_matrix_expand_row2(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 512, 513, 514, 515); + poly_nttunpack(&rowa->vec[0]); + poly_nttunpack(&rowa->vec[1]); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); +} + +void polyvec_matrix_expand_row3(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 768, 769, 770, 771); + poly_nttunpack(&rowa->vec[0]); + poly_nttunpack(&rowa->vec[1]); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); +} + +#elif K == 6 && L == 5 +void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { + polyvecl tmp; + polyvec_matrix_expand_row0(&mat[0], &mat[1], rho); + polyvec_matrix_expand_row1(&mat[1], &mat[2], rho); + polyvec_matrix_expand_row2(&mat[2], &mat[3], rho); + polyvec_matrix_expand_row3(&mat[3], NULL, rho); + polyvec_matrix_expand_row4(&mat[4], &mat[5], rho); + polyvec_matrix_expand_row5(&mat[5], &tmp, rho); +} + +void polyvec_matrix_expand_row0(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 0, 1, 2, 3); + poly_uniform_4x(&rowa->vec[4], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 4, 256, 257, 258); + poly_nttunpack(&rowa->vec[0]); + poly_nttunpack(&rowa->vec[1]); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowb->vec[0]); + poly_nttunpack(&rowb->vec[1]); + poly_nttunpack(&rowb->vec[2]); +} + +void polyvec_matrix_expand_row1(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowb->vec[0], &rowb->vec[1], rho, 259, 260, 512, 513); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowb->vec[0]); + poly_nttunpack(&rowb->vec[1]); +} + +void polyvec_matrix_expand_row2(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[2], &rowa->vec[3], &rowa->vec[4], &rowb->vec[0], rho, 514, 515, 516, 768); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowb->vec[0]); +} + +void polyvec_matrix_expand_row3(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[1], &rowa->vec[2], &rowa->vec[3], &rowa->vec[4], rho, 769, 770, 771, 772); + poly_nttunpack(&rowa->vec[1]); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); +} + +void polyvec_matrix_expand_row4(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 1024, 1025, 1026, 1027); + poly_uniform_4x(&rowa->vec[4], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 1028, 1280, 1281, 1282); + poly_nttunpack(&rowa->vec[0]); + poly_nttunpack(&rowa->vec[1]); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowb->vec[0]); + poly_nttunpack(&rowb->vec[1]); + poly_nttunpack(&rowb->vec[2]); +} + +void polyvec_matrix_expand_row5(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowb->vec[0], &rowb->vec[1], rho, 1283, 1284, 1536, 1537); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); +} + +#elif K == 8 && L == 7 +void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { + polyvec_matrix_expand_row0(&mat[0], &mat[1], rho); + polyvec_matrix_expand_row1(&mat[1], &mat[2], rho); + polyvec_matrix_expand_row2(&mat[2], &mat[3], rho); + polyvec_matrix_expand_row3(&mat[3], NULL, rho); + polyvec_matrix_expand_row4(&mat[4], &mat[5], rho); + polyvec_matrix_expand_row5(&mat[5], &mat[6], rho); + polyvec_matrix_expand_row6(&mat[6], &mat[7], rho); + polyvec_matrix_expand_row7(&mat[7], NULL, rho); +} + +void polyvec_matrix_expand_row0(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 0, 1, 2, 3); + poly_uniform_4x(&rowa->vec[4], &rowa->vec[5], &rowa->vec[6], &rowb->vec[0], rho, 4, 5, 6, 256); + poly_nttunpack(&rowa->vec[0]); + poly_nttunpack(&rowa->vec[1]); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowa->vec[5]); + poly_nttunpack(&rowa->vec[6]); + poly_nttunpack(&rowb->vec[0]); +} + +void polyvec_matrix_expand_row1(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[1], &rowa->vec[2], &rowa->vec[3], &rowa->vec[4], rho, 257, 258, 259, 260); + poly_uniform_4x(&rowa->vec[5], &rowa->vec[6], &rowb->vec[0], &rowb->vec[1], rho, 261, 262, 512, 513); + poly_nttunpack(&rowa->vec[1]); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowa->vec[5]); + poly_nttunpack(&rowa->vec[6]); + poly_nttunpack(&rowb->vec[0]); + poly_nttunpack(&rowb->vec[1]); +} + +void polyvec_matrix_expand_row2(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[2], &rowa->vec[3], &rowa->vec[4], &rowa->vec[5], rho, 514, 515, 516, 517); + poly_uniform_4x(&rowa->vec[6], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 518, 768, 769, 770); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowa->vec[5]); + poly_nttunpack(&rowa->vec[6]); + poly_nttunpack(&rowb->vec[0]); + poly_nttunpack(&rowb->vec[1]); + poly_nttunpack(&rowb->vec[2]); +} + +void polyvec_matrix_expand_row3(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowa->vec[5], &rowa->vec[6], rho, 771, 772, 773, 774); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowa->vec[5]); + poly_nttunpack(&rowa->vec[6]); +} + +void polyvec_matrix_expand_row4(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 1024, 1025, 1026, 1027); + poly_uniform_4x(&rowa->vec[4], &rowa->vec[5], &rowa->vec[6], &rowb->vec[0], rho, 1028, 1029, 1030, 1280); + poly_nttunpack(&rowa->vec[0]); + poly_nttunpack(&rowa->vec[1]); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowa->vec[5]); + poly_nttunpack(&rowa->vec[6]); + poly_nttunpack(&rowb->vec[0]); +} + +void polyvec_matrix_expand_row5(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[1], &rowa->vec[2], &rowa->vec[3], &rowa->vec[4], rho, 1281, 1282, 1283, 1284); + poly_uniform_4x(&rowa->vec[5], &rowa->vec[6], &rowb->vec[0], &rowb->vec[1], rho, 1285, 1286, 1536, 1537); + poly_nttunpack(&rowa->vec[1]); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowa->vec[5]); + poly_nttunpack(&rowa->vec[6]); + poly_nttunpack(&rowb->vec[0]); + poly_nttunpack(&rowb->vec[1]); +} + +void polyvec_matrix_expand_row6(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[2], &rowa->vec[3], &rowa->vec[4], &rowa->vec[5], rho, 1538, 1539, 1540, 1541); + poly_uniform_4x(&rowa->vec[6], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 1542, 1792, 1793, 1794); + poly_nttunpack(&rowa->vec[2]); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowa->vec[5]); + poly_nttunpack(&rowa->vec[6]); + poly_nttunpack(&rowb->vec[0]); + poly_nttunpack(&rowb->vec[1]); + poly_nttunpack(&rowb->vec[2]); +} + +void polyvec_matrix_expand_row7(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) { + poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowa->vec[5], &rowa->vec[6], rho, 1795, 1796, 1797, 1798); + poly_nttunpack(&rowa->vec[3]); + poly_nttunpack(&rowa->vec[4]); + poly_nttunpack(&rowa->vec[5]); + poly_nttunpack(&rowa->vec[6]); +} + +#else +#error +#endif + +void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); +} + +/**************************************************************/ +/************ Vectors of polynomials of length L **************/ +/**************************************************************/ + +void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_uniform_eta(&v->vec[i], seed, nonce++); +} + +void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_uniform_gamma1(&v->vec[i], seed, L*nonce + i); +} + +void polyvecl_reduce(polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_reduce(&v->vec[i]); +} + +/************************************************* +* Name: polyvecl_add +* +* Description: Add vectors of polynomials of length L. +* No modular reduction is performed. +* +* Arguments: - polyvecl *w: pointer to output vector +* - const polyvecl *u: pointer to first summand +* - const polyvecl *v: pointer to second summand +**************************************************/ +void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyvecl_ntt +* +* Description: Forward NTT of all polynomials in vector of length L. Output +* coefficients can be up to 16*Q larger than input coefficients. +* +* Arguments: - polyvecl *v: pointer to input/output vector +**************************************************/ +void polyvecl_ntt(polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_ntt(&v->vec[i]); +} + +void polyvecl_invntt_tomont(polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_invntt_tomont(&v->vec[i]); +} + +void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); +} + +/************************************************* +* Name: polyvecl_pointwise_acc_montgomery +* +* Description: Pointwise multiply vectors of polynomials of length L, multiply +* resulting vector by 2^{-32} and add (accumulate) polynomials +* in it. Input/output vectors are in NTT domain representation. +* +* Arguments: - poly *w: output polynomial +* - const polyvecl *u: pointer to first input vector +* - const polyvecl *v: pointer to second input vector +**************************************************/ +void polyvecl_pointwise_acc_montgomery(poly *w, const polyvecl *u, const polyvecl *v) { + pointwise_acc_avx(w->vec, u->vec->vec, v->vec->vec, qdata.vec); +} + +/************************************************* +* Name: polyvecl_chknorm +* +* Description: Check infinity norm of polynomials in vector of length L. +* Assumes input polyvecl to be reduced by polyvecl_reduce(). +* +* Arguments: - const polyvecl *v: pointer to vector +* - int32_t B: norm bound +* +* Returns 0 if norm of all polynomials is strictly smaller than B <= (Q-1)/8 +* and 1 otherwise. +**************************************************/ +int polyvecl_chknorm(const polyvecl *v, int32_t bound) { + unsigned int i; + + for(i = 0; i < L; ++i) + if(poly_chknorm(&v->vec[i], bound)) + return 1; + + return 0; +} + +/**************************************************************/ +/************ Vectors of polynomials of length K **************/ +/**************************************************************/ + +void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_uniform_eta(&v->vec[i], seed, nonce++); +} + +/************************************************* +* Name: polyveck_reduce +* +* Description: Reduce coefficients of polynomials in vector of length K +* to representatives in [-6283009,6283008]. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_reduce(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_reduce(&v->vec[i]); +} + +/************************************************* +* Name: polyveck_caddq +* +* Description: For all coefficients of polynomials in vector of length K +* add Q if coefficient is negative. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_caddq(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_caddq(&v->vec[i]); +} + +/************************************************* +* Name: polyveck_add +* +* Description: Add vectors of polynomials of length K. +* No modular reduction is performed. +* +* Arguments: - polyveck *w: pointer to output vector +* - const polyveck *u: pointer to first summand +* - const polyveck *v: pointer to second summand +**************************************************/ +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_sub +* +* Description: Subtract vectors of polynomials of length K. +* No modular reduction is performed. +* +* Arguments: - polyveck *w: pointer to output vector +* - const polyveck *u: pointer to first input vector +* - const polyveck *v: pointer to second input vector to be +* subtracted from first input vector +**************************************************/ +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_shiftl +* +* Description: Multiply vector of polynomials of Length K by 2^D without modular +* reduction. Assumes input coefficients to be less than 2^{31-D}. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_shiftl(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_shiftl(&v->vec[i]); +} + +/************************************************* +* Name: polyveck_ntt +* +* Description: Forward NTT of all polynomials in vector of length K. Output +* coefficients can be up to 16*Q larger than input coefficients. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_ntt(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_ntt(&v->vec[i]); +} + +/************************************************* +* Name: polyveck_invntt_tomont +* +* Description: Inverse NTT and multiplication by 2^{32} of polynomials +* in vector of length K. Input coefficients need to be less +* than 2*Q. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_invntt_tomont(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_invntt_tomont(&v->vec[i]); +} + +void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); +} + +/************************************************* +* Name: polyveck_chknorm +* +* Description: Check infinity norm of polynomials in vector of length K. +* Assumes input polyveck to be reduced by polyveck_reduce(). +* +* Arguments: - const polyveck *v: pointer to vector +* - int32_t B: norm bound +* +* Returns 0 if norm of all polynomials are strictly smaller than B <= (Q-1)/8 +* and 1 otherwise. +**************************************************/ +int polyveck_chknorm(const polyveck *v, int32_t bound) { + unsigned int i; + + for(i = 0; i < K; ++i) + if(poly_chknorm(&v->vec[i], bound)) + return 1; + + return 0; +} + +/************************************************* +* Name: polyveck_power2round +* +* Description: For all coefficients a of polynomials in vector of length K, +* compute a0, a1 such that a mod^+ Q = a1*2^D + a0 +* with -2^{D-1} < a0 <= 2^{D-1}. Assumes coefficients to be +* standard representatives. +* +* Arguments: - polyveck *v1: pointer to output vector of polynomials with +* coefficients a1 +* - polyveck *v0: pointer to output vector of polynomials with +* coefficients a0 +* - const polyveck *v: pointer to input vector +**************************************************/ +void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_power2round(&v1->vec[i], &v0->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_decompose +* +* Description: For all coefficients a of polynomials in vector of length K, +* compute high and low bits a0, a1 such a mod^+ Q = a1*ALPHA + a0 +* with -ALPHA/2 < a0 <= ALPHA/2 except a1 = (Q-1)/ALPHA where we +* set a1 = 0 and -ALPHA/2 <= a0 = a mod Q - Q < 0. +* Assumes coefficients to be standard representatives. +* +* Arguments: - polyveck *v1: pointer to output vector of polynomials with +* coefficients a1 +* - polyveck *v0: pointer to output vector of polynomials with +* coefficients a0 +* - const polyveck *v: pointer to input vector +**************************************************/ +void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_decompose(&v1->vec[i], &v0->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_make_hint +* +* Description: Compute hint vector. +* +* Arguments: - uint8_t *hint: pointer to output hint array +* - const polyveck *v0: pointer to low part of input vector +* - const polyveck *v1: pointer to high part of input vector +* +* Returns number of 1 bits. +**************************************************/ +unsigned int polyveck_make_hint(uint8_t *hint, const polyveck *v0, const polyveck *v1) +{ + unsigned int i, n = 0; + + for(i = 0; i < K; ++i) + n += poly_make_hint(&hint[n], &v0->vec[i], &v1->vec[i]); + + return n; +} + +/************************************************* +* Name: polyveck_use_hint +* +* Description: Use hint vector to correct the high bits of input vector. +* +* Arguments: - polyveck *w: pointer to output vector of polynomials with +* corrected high bits +* - const polyveck *u: pointer to input vector +* - const polyveck *h: pointer to input hint vector +**************************************************/ +void polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_use_hint(&w->vec[i], &u->vec[i], &h->vec[i]); +} + +void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1) { + unsigned int i; + + for(i = 0; i < K; ++i) + polyw1_pack(&r[i*POLYW1_PACKEDBYTES], &w1->vec[i]); +} diff --git a/avx2/polyvec.h b/avx2/polyvec.h new file mode 100644 index 0000000..1b6dc87 --- /dev/null +++ b/avx2/polyvec.h @@ -0,0 +1,105 @@ +#ifndef POLYVEC_H +#define POLYVEC_H + +#include +#include "params.h" +#include "poly.h" + +/* Vectors of polynomials of length L */ +typedef struct { + poly vec[L]; +} polyvecl; + +#define polyvecl_uniform_eta DILITHIUM_NAMESPACE(polyvecl_uniform_eta) +void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyvecl_uniform_gamma1 DILITHIUM_NAMESPACE(polyvecl_uniform_gamma1) +void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyvecl_reduce DILITHIUM_NAMESPACE(polyvecl_reduce) +void polyvecl_reduce(polyvecl *v); + +#define polyvecl_add DILITHIUM_NAMESPACE(polyvecl_add) +void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v); + +#define polyvecl_ntt DILITHIUM_NAMESPACE(polyvecl_ntt) +void polyvecl_ntt(polyvecl *v); +#define polyvecl_invntt_tomont DILITHIUM_NAMESPACE(polyvecl_invntt_tomont) +void polyvecl_invntt_tomont(polyvecl *v); +#define polyvecl_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyvecl_pointwise_poly_montgomery) +void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v); +#define polyvecl_pointwise_acc_montgomery \ + DILITHIUM_NAMESPACE(polyvecl_pointwise_acc_montgomery) +void polyvecl_pointwise_acc_montgomery(poly *w, + const polyvecl *u, + const polyvecl *v); + +#define polyvecl_chknorm DILITHIUM_NAMESPACE(polyvecl_chknorm) +int polyvecl_chknorm(const polyvecl *v, int32_t B); + +/* Vectors of polynomials of length K */ +typedef struct { + poly vec[K]; +} polyveck; + +#define polyveck_uniform_eta DILITHIUM_NAMESPACE(polyveck_uniform_eta) +void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyveck_reduce DILITHIUM_NAMESPACE(polyveck_reduce) +void polyveck_reduce(polyveck *v); +#define polyveck_caddq DILITHIUM_NAMESPACE(polyveck_caddq) +void polyveck_caddq(polyveck *v); + +#define polyveck_add DILITHIUM_NAMESPACE(polyveck_add) +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_sub DILITHIUM_NAMESPACE(polyveck_sub) +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_shiftl DILITHIUM_NAMESPACE(polyveck_shiftl) +void polyveck_shiftl(polyveck *v); + +#define polyveck_ntt DILITHIUM_NAMESPACE(polyveck_ntt) +void polyveck_ntt(polyveck *v); +#define polyveck_invntt_tomont DILITHIUM_NAMESPACE(polyveck_invntt_tomont) +void polyveck_invntt_tomont(polyveck *v); +#define polyveck_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyveck_pointwise_poly_montgomery) +void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v); + +#define polyveck_chknorm DILITHIUM_NAMESPACE(polyveck_chknorm) +int polyveck_chknorm(const polyveck *v, int32_t B); + +#define polyveck_power2round DILITHIUM_NAMESPACE(polyveck_power2round) +void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v); +#define polyveck_decompose DILITHIUM_NAMESPACE(polyveck_decompose) +void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v); +#define polyveck_make_hint DILITHIUM_NAMESPACE(polyveck_make_hint) +unsigned int polyveck_make_hint(uint8_t *hint, const polyveck *v0, const polyveck *v1); +#define polyveck_use_hint DILITHIUM_NAMESPACE(polyveck_use_hint) +void polyveck_use_hint(polyveck *w, const polyveck *v, const polyveck *h); + +#define polyveck_pack_w1 DILITHIUM_NAMESPACE(polyveck_pack_w1) +void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1); + +#define polyvec_matrix_expand DILITHIUM_NAMESPACE(polyvec_matrix_expand) +void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); + +#define polyvec_matrix_expand_row0 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row0) +void polyvec_matrix_expand_row0(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); +#define polyvec_matrix_expand_row1 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row1) +void polyvec_matrix_expand_row1(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); +#define polyvec_matrix_expand_row2 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row2) +void polyvec_matrix_expand_row2(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); +#define polyvec_matrix_expand_row3 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row3) +void polyvec_matrix_expand_row3(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); +#define polyvec_matrix_expand_row4 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row4) +void polyvec_matrix_expand_row4(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); +#define polyvec_matrix_expand_row5 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row5) +void polyvec_matrix_expand_row5(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); +#define polyvec_matrix_expand_row6 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row6) +void polyvec_matrix_expand_row6(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); +#define polyvec_matrix_expand_row7 DILITHIUM_NAMESPACE(polyvec_matrix_expand_row7) +void polyvec_matrix_expand_row7(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]); + +#define polyvec_matrix_pointwise_montgomery DILITHIUM_NAMESPACE(polyvec_matrix_pointwise_montgomery) +void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v); + +#endif diff --git a/avx2/randombytes.c b/avx2/randombytes.c new file mode 120000 index 0000000..59a42a5 --- /dev/null +++ b/avx2/randombytes.c @@ -0,0 +1 @@ +../ref/randombytes.c \ No newline at end of file diff --git a/avx2/randombytes.h b/avx2/randombytes.h new file mode 120000 index 0000000..055e443 --- /dev/null +++ b/avx2/randombytes.h @@ -0,0 +1 @@ +../ref/randombytes.h \ No newline at end of file diff --git a/avx2/rejsample.c b/avx2/rejsample.c new file mode 100644 index 0000000..8b1dde4 --- /dev/null +++ b/avx2/rejsample.c @@ -0,0 +1,476 @@ +#include +#include +#include "params.h" +#include "rejsample.h" +#include "symmetric.h" + +const uint8_t idxlut[256][8] = { + { 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 0, 0, 0, 0, 0, 0, 0}, + { 0, 1, 0, 0, 0, 0, 0, 0}, + { 2, 0, 0, 0, 0, 0, 0, 0}, + { 0, 2, 0, 0, 0, 0, 0, 0}, + { 1, 2, 0, 0, 0, 0, 0, 0}, + { 0, 1, 2, 0, 0, 0, 0, 0}, + { 3, 0, 0, 0, 0, 0, 0, 0}, + { 0, 3, 0, 0, 0, 0, 0, 0}, + { 1, 3, 0, 0, 0, 0, 0, 0}, + { 0, 1, 3, 0, 0, 0, 0, 0}, + { 2, 3, 0, 0, 0, 0, 0, 0}, + { 0, 2, 3, 0, 0, 0, 0, 0}, + { 1, 2, 3, 0, 0, 0, 0, 0}, + { 0, 1, 2, 3, 0, 0, 0, 0}, + { 4, 0, 0, 0, 0, 0, 0, 0}, + { 0, 4, 0, 0, 0, 0, 0, 0}, + { 1, 4, 0, 0, 0, 0, 0, 0}, + { 0, 1, 4, 0, 0, 0, 0, 0}, + { 2, 4, 0, 0, 0, 0, 0, 0}, + { 0, 2, 4, 0, 0, 0, 0, 0}, + { 1, 2, 4, 0, 0, 0, 0, 0}, + { 0, 1, 2, 4, 0, 0, 0, 0}, + { 3, 4, 0, 0, 0, 0, 0, 0}, + { 0, 3, 4, 0, 0, 0, 0, 0}, + { 1, 3, 4, 0, 0, 0, 0, 0}, + { 0, 1, 3, 4, 0, 0, 0, 0}, + { 2, 3, 4, 0, 0, 0, 0, 0}, + { 0, 2, 3, 4, 0, 0, 0, 0}, + { 1, 2, 3, 4, 0, 0, 0, 0}, + { 0, 1, 2, 3, 4, 0, 0, 0}, + { 5, 0, 0, 0, 0, 0, 0, 0}, + { 0, 5, 0, 0, 0, 0, 0, 0}, + { 1, 5, 0, 0, 0, 0, 0, 0}, + { 0, 1, 5, 0, 0, 0, 0, 0}, + { 2, 5, 0, 0, 0, 0, 0, 0}, + { 0, 2, 5, 0, 0, 0, 0, 0}, + { 1, 2, 5, 0, 0, 0, 0, 0}, + { 0, 1, 2, 5, 0, 0, 0, 0}, + { 3, 5, 0, 0, 0, 0, 0, 0}, + { 0, 3, 5, 0, 0, 0, 0, 0}, + { 1, 3, 5, 0, 0, 0, 0, 0}, + { 0, 1, 3, 5, 0, 0, 0, 0}, + { 2, 3, 5, 0, 0, 0, 0, 0}, + { 0, 2, 3, 5, 0, 0, 0, 0}, + { 1, 2, 3, 5, 0, 0, 0, 0}, + { 0, 1, 2, 3, 5, 0, 0, 0}, + { 4, 5, 0, 0, 0, 0, 0, 0}, + { 0, 4, 5, 0, 0, 0, 0, 0}, + { 1, 4, 5, 0, 0, 0, 0, 0}, + { 0, 1, 4, 5, 0, 0, 0, 0}, + { 2, 4, 5, 0, 0, 0, 0, 0}, + { 0, 2, 4, 5, 0, 0, 0, 0}, + { 1, 2, 4, 5, 0, 0, 0, 0}, + { 0, 1, 2, 4, 5, 0, 0, 0}, + { 3, 4, 5, 0, 0, 0, 0, 0}, + { 0, 3, 4, 5, 0, 0, 0, 0}, + { 1, 3, 4, 5, 0, 0, 0, 0}, + { 0, 1, 3, 4, 5, 0, 0, 0}, + { 2, 3, 4, 5, 0, 0, 0, 0}, + { 0, 2, 3, 4, 5, 0, 0, 0}, + { 1, 2, 3, 4, 5, 0, 0, 0}, + { 0, 1, 2, 3, 4, 5, 0, 0}, + { 6, 0, 0, 0, 0, 0, 0, 0}, + { 0, 6, 0, 0, 0, 0, 0, 0}, + { 1, 6, 0, 0, 0, 0, 0, 0}, + { 0, 1, 6, 0, 0, 0, 0, 0}, + { 2, 6, 0, 0, 0, 0, 0, 0}, + { 0, 2, 6, 0, 0, 0, 0, 0}, + { 1, 2, 6, 0, 0, 0, 0, 0}, + { 0, 1, 2, 6, 0, 0, 0, 0}, + { 3, 6, 0, 0, 0, 0, 0, 0}, + { 0, 3, 6, 0, 0, 0, 0, 0}, + { 1, 3, 6, 0, 0, 0, 0, 0}, + { 0, 1, 3, 6, 0, 0, 0, 0}, + { 2, 3, 6, 0, 0, 0, 0, 0}, + { 0, 2, 3, 6, 0, 0, 0, 0}, + { 1, 2, 3, 6, 0, 0, 0, 0}, + { 0, 1, 2, 3, 6, 0, 0, 0}, + { 4, 6, 0, 0, 0, 0, 0, 0}, + { 0, 4, 6, 0, 0, 0, 0, 0}, + { 1, 4, 6, 0, 0, 0, 0, 0}, + { 0, 1, 4, 6, 0, 0, 0, 0}, + { 2, 4, 6, 0, 0, 0, 0, 0}, + { 0, 2, 4, 6, 0, 0, 0, 0}, + { 1, 2, 4, 6, 0, 0, 0, 0}, + { 0, 1, 2, 4, 6, 0, 0, 0}, + { 3, 4, 6, 0, 0, 0, 0, 0}, + { 0, 3, 4, 6, 0, 0, 0, 0}, + { 1, 3, 4, 6, 0, 0, 0, 0}, + { 0, 1, 3, 4, 6, 0, 0, 0}, + { 2, 3, 4, 6, 0, 0, 0, 0}, + { 0, 2, 3, 4, 6, 0, 0, 0}, + { 1, 2, 3, 4, 6, 0, 0, 0}, + { 0, 1, 2, 3, 4, 6, 0, 0}, + { 5, 6, 0, 0, 0, 0, 0, 0}, + { 0, 5, 6, 0, 0, 0, 0, 0}, + { 1, 5, 6, 0, 0, 0, 0, 0}, + { 0, 1, 5, 6, 0, 0, 0, 0}, + { 2, 5, 6, 0, 0, 0, 0, 0}, + { 0, 2, 5, 6, 0, 0, 0, 0}, + { 1, 2, 5, 6, 0, 0, 0, 0}, + { 0, 1, 2, 5, 6, 0, 0, 0}, + { 3, 5, 6, 0, 0, 0, 0, 0}, + { 0, 3, 5, 6, 0, 0, 0, 0}, + { 1, 3, 5, 6, 0, 0, 0, 0}, + { 0, 1, 3, 5, 6, 0, 0, 0}, + { 2, 3, 5, 6, 0, 0, 0, 0}, + { 0, 2, 3, 5, 6, 0, 0, 0}, + { 1, 2, 3, 5, 6, 0, 0, 0}, + { 0, 1, 2, 3, 5, 6, 0, 0}, + { 4, 5, 6, 0, 0, 0, 0, 0}, + { 0, 4, 5, 6, 0, 0, 0, 0}, + { 1, 4, 5, 6, 0, 0, 0, 0}, + { 0, 1, 4, 5, 6, 0, 0, 0}, + { 2, 4, 5, 6, 0, 0, 0, 0}, + { 0, 2, 4, 5, 6, 0, 0, 0}, + { 1, 2, 4, 5, 6, 0, 0, 0}, + { 0, 1, 2, 4, 5, 6, 0, 0}, + { 3, 4, 5, 6, 0, 0, 0, 0}, + { 0, 3, 4, 5, 6, 0, 0, 0}, + { 1, 3, 4, 5, 6, 0, 0, 0}, + { 0, 1, 3, 4, 5, 6, 0, 0}, + { 2, 3, 4, 5, 6, 0, 0, 0}, + { 0, 2, 3, 4, 5, 6, 0, 0}, + { 1, 2, 3, 4, 5, 6, 0, 0}, + { 0, 1, 2, 3, 4, 5, 6, 0}, + { 7, 0, 0, 0, 0, 0, 0, 0}, + { 0, 7, 0, 0, 0, 0, 0, 0}, + { 1, 7, 0, 0, 0, 0, 0, 0}, + { 0, 1, 7, 0, 0, 0, 0, 0}, + { 2, 7, 0, 0, 0, 0, 0, 0}, + { 0, 2, 7, 0, 0, 0, 0, 0}, + { 1, 2, 7, 0, 0, 0, 0, 0}, + { 0, 1, 2, 7, 0, 0, 0, 0}, + { 3, 7, 0, 0, 0, 0, 0, 0}, + { 0, 3, 7, 0, 0, 0, 0, 0}, + { 1, 3, 7, 0, 0, 0, 0, 0}, + { 0, 1, 3, 7, 0, 0, 0, 0}, + { 2, 3, 7, 0, 0, 0, 0, 0}, + { 0, 2, 3, 7, 0, 0, 0, 0}, + { 1, 2, 3, 7, 0, 0, 0, 0}, + { 0, 1, 2, 3, 7, 0, 0, 0}, + { 4, 7, 0, 0, 0, 0, 0, 0}, + { 0, 4, 7, 0, 0, 0, 0, 0}, + { 1, 4, 7, 0, 0, 0, 0, 0}, + { 0, 1, 4, 7, 0, 0, 0, 0}, + { 2, 4, 7, 0, 0, 0, 0, 0}, + { 0, 2, 4, 7, 0, 0, 0, 0}, + { 1, 2, 4, 7, 0, 0, 0, 0}, + { 0, 1, 2, 4, 7, 0, 0, 0}, + { 3, 4, 7, 0, 0, 0, 0, 0}, + { 0, 3, 4, 7, 0, 0, 0, 0}, + { 1, 3, 4, 7, 0, 0, 0, 0}, + { 0, 1, 3, 4, 7, 0, 0, 0}, + { 2, 3, 4, 7, 0, 0, 0, 0}, + { 0, 2, 3, 4, 7, 0, 0, 0}, + { 1, 2, 3, 4, 7, 0, 0, 0}, + { 0, 1, 2, 3, 4, 7, 0, 0}, + { 5, 7, 0, 0, 0, 0, 0, 0}, + { 0, 5, 7, 0, 0, 0, 0, 0}, + { 1, 5, 7, 0, 0, 0, 0, 0}, + { 0, 1, 5, 7, 0, 0, 0, 0}, + { 2, 5, 7, 0, 0, 0, 0, 0}, + { 0, 2, 5, 7, 0, 0, 0, 0}, + { 1, 2, 5, 7, 0, 0, 0, 0}, + { 0, 1, 2, 5, 7, 0, 0, 0}, + { 3, 5, 7, 0, 0, 0, 0, 0}, + { 0, 3, 5, 7, 0, 0, 0, 0}, + { 1, 3, 5, 7, 0, 0, 0, 0}, + { 0, 1, 3, 5, 7, 0, 0, 0}, + { 2, 3, 5, 7, 0, 0, 0, 0}, + { 0, 2, 3, 5, 7, 0, 0, 0}, + { 1, 2, 3, 5, 7, 0, 0, 0}, + { 0, 1, 2, 3, 5, 7, 0, 0}, + { 4, 5, 7, 0, 0, 0, 0, 0}, + { 0, 4, 5, 7, 0, 0, 0, 0}, + { 1, 4, 5, 7, 0, 0, 0, 0}, + { 0, 1, 4, 5, 7, 0, 0, 0}, + { 2, 4, 5, 7, 0, 0, 0, 0}, + { 0, 2, 4, 5, 7, 0, 0, 0}, + { 1, 2, 4, 5, 7, 0, 0, 0}, + { 0, 1, 2, 4, 5, 7, 0, 0}, + { 3, 4, 5, 7, 0, 0, 0, 0}, + { 0, 3, 4, 5, 7, 0, 0, 0}, + { 1, 3, 4, 5, 7, 0, 0, 0}, + { 0, 1, 3, 4, 5, 7, 0, 0}, + { 2, 3, 4, 5, 7, 0, 0, 0}, + { 0, 2, 3, 4, 5, 7, 0, 0}, + { 1, 2, 3, 4, 5, 7, 0, 0}, + { 0, 1, 2, 3, 4, 5, 7, 0}, + { 6, 7, 0, 0, 0, 0, 0, 0}, + { 0, 6, 7, 0, 0, 0, 0, 0}, + { 1, 6, 7, 0, 0, 0, 0, 0}, + { 0, 1, 6, 7, 0, 0, 0, 0}, + { 2, 6, 7, 0, 0, 0, 0, 0}, + { 0, 2, 6, 7, 0, 0, 0, 0}, + { 1, 2, 6, 7, 0, 0, 0, 0}, + { 0, 1, 2, 6, 7, 0, 0, 0}, + { 3, 6, 7, 0, 0, 0, 0, 0}, + { 0, 3, 6, 7, 0, 0, 0, 0}, + { 1, 3, 6, 7, 0, 0, 0, 0}, + { 0, 1, 3, 6, 7, 0, 0, 0}, + { 2, 3, 6, 7, 0, 0, 0, 0}, + { 0, 2, 3, 6, 7, 0, 0, 0}, + { 1, 2, 3, 6, 7, 0, 0, 0}, + { 0, 1, 2, 3, 6, 7, 0, 0}, + { 4, 6, 7, 0, 0, 0, 0, 0}, + { 0, 4, 6, 7, 0, 0, 0, 0}, + { 1, 4, 6, 7, 0, 0, 0, 0}, + { 0, 1, 4, 6, 7, 0, 0, 0}, + { 2, 4, 6, 7, 0, 0, 0, 0}, + { 0, 2, 4, 6, 7, 0, 0, 0}, + { 1, 2, 4, 6, 7, 0, 0, 0}, + { 0, 1, 2, 4, 6, 7, 0, 0}, + { 3, 4, 6, 7, 0, 0, 0, 0}, + { 0, 3, 4, 6, 7, 0, 0, 0}, + { 1, 3, 4, 6, 7, 0, 0, 0}, + { 0, 1, 3, 4, 6, 7, 0, 0}, + { 2, 3, 4, 6, 7, 0, 0, 0}, + { 0, 2, 3, 4, 6, 7, 0, 0}, + { 1, 2, 3, 4, 6, 7, 0, 0}, + { 0, 1, 2, 3, 4, 6, 7, 0}, + { 5, 6, 7, 0, 0, 0, 0, 0}, + { 0, 5, 6, 7, 0, 0, 0, 0}, + { 1, 5, 6, 7, 0, 0, 0, 0}, + { 0, 1, 5, 6, 7, 0, 0, 0}, + { 2, 5, 6, 7, 0, 0, 0, 0}, + { 0, 2, 5, 6, 7, 0, 0, 0}, + { 1, 2, 5, 6, 7, 0, 0, 0}, + { 0, 1, 2, 5, 6, 7, 0, 0}, + { 3, 5, 6, 7, 0, 0, 0, 0}, + { 0, 3, 5, 6, 7, 0, 0, 0}, + { 1, 3, 5, 6, 7, 0, 0, 0}, + { 0, 1, 3, 5, 6, 7, 0, 0}, + { 2, 3, 5, 6, 7, 0, 0, 0}, + { 0, 2, 3, 5, 6, 7, 0, 0}, + { 1, 2, 3, 5, 6, 7, 0, 0}, + { 0, 1, 2, 3, 5, 6, 7, 0}, + { 4, 5, 6, 7, 0, 0, 0, 0}, + { 0, 4, 5, 6, 7, 0, 0, 0}, + { 1, 4, 5, 6, 7, 0, 0, 0}, + { 0, 1, 4, 5, 6, 7, 0, 0}, + { 2, 4, 5, 6, 7, 0, 0, 0}, + { 0, 2, 4, 5, 6, 7, 0, 0}, + { 1, 2, 4, 5, 6, 7, 0, 0}, + { 0, 1, 2, 4, 5, 6, 7, 0}, + { 3, 4, 5, 6, 7, 0, 0, 0}, + { 0, 3, 4, 5, 6, 7, 0, 0}, + { 1, 3, 4, 5, 6, 7, 0, 0}, + { 0, 1, 3, 4, 5, 6, 7, 0}, + { 2, 3, 4, 5, 6, 7, 0, 0}, + { 0, 2, 3, 4, 5, 6, 7, 0}, + { 1, 2, 3, 4, 5, 6, 7, 0}, + { 0, 1, 2, 3, 4, 5, 6, 7} +}; + +unsigned int rej_uniform_avx(int32_t * restrict r, const uint8_t buf[REJ_UNIFORM_BUFLEN+8]) +{ + unsigned int ctr, pos; + uint32_t good; + __m256i d, tmp; + const __m256i bound = _mm256_set1_epi32(Q); + const __m256i mask = _mm256_set1_epi32(0x7FFFFF); + const __m256i idx8 = _mm256_set_epi8(-1,15,14,13,-1,12,11,10, + -1, 9, 8, 7,-1, 6, 5, 4, + -1,11,10, 9,-1, 8, 7, 6, + -1, 5, 4, 3,-1, 2, 1, 0); + + ctr = pos = 0; + while(pos <= REJ_UNIFORM_BUFLEN - 24) { + d = _mm256_loadu_si256((__m256i *)&buf[pos]); + d = _mm256_permute4x64_epi64(d, 0x94); + d = _mm256_shuffle_epi8(d, idx8); + d = _mm256_and_si256(d, mask); + pos += 24; + + tmp = _mm256_sub_epi32(d, bound); + good = _mm256_movemask_ps((__m256)tmp); + tmp = _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i *)&idxlut[good])); + d = _mm256_permutevar8x32_epi32(d, tmp); + + _mm256_storeu_si256((__m256i *)&r[ctr], d); + ctr += _mm_popcnt_u32(good); + + if(ctr > N - 8) break; + } + + uint32_t t; + while(ctr < N && pos <= REJ_UNIFORM_BUFLEN - 3) { + t = buf[pos++]; + t |= (uint32_t)buf[pos++] << 8; + t |= (uint32_t)buf[pos++] << 16; + t &= 0x7FFFFF; + + if(t < Q) + r[ctr++] = t; + } + + return ctr; +} + +#if ETA == 2 +unsigned int rej_eta_avx(int32_t * restrict r, const uint8_t buf[REJ_UNIFORM_ETA_BUFLEN]) { + unsigned int ctr, pos; + uint32_t good; + __m256i f0, f1, f2; + __m128i g0, g1; + const __m256i mask = _mm256_set1_epi8(15); + const __m256i eta = _mm256_set1_epi8(ETA); + const __m256i bound = mask; + const __m256i v = _mm256_set1_epi32(-6560); + const __m256i p = _mm256_set1_epi32(5); + + ctr = pos = 0; + while(ctr <= N - 8 && pos <= REJ_UNIFORM_ETA_BUFLEN - 16) { + f0 = _mm256_cvtepu8_epi16(_mm_loadu_si128((__m128i *)&buf[pos])); + f1 = _mm256_slli_epi16(f0,4); + f0 = _mm256_or_si256(f0,f1); + f0 = _mm256_and_si256(f0,mask); + + f1 = _mm256_sub_epi8(f0,bound); + f0 = _mm256_sub_epi8(eta,f0); + good = _mm256_movemask_epi8(f1); + + g0 = _mm256_castsi256_si128(f0); + g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); + g1 = _mm_shuffle_epi8(g0,g1); + f1 = _mm256_cvtepi8_epi32(g1); + f2 = _mm256_mulhrs_epi16(f1,v); + f2 = _mm256_mullo_epi16(f2,p); + f1 = _mm256_add_epi32(f1,f2); + _mm256_storeu_si256((__m256i *)&r[ctr],f1); + ctr += _mm_popcnt_u32(good & 0xFF); + good >>= 8; + pos += 4; + + if(ctr > N - 8) break; + g0 = _mm_bsrli_si128(g0,8); + g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); + g1 = _mm_shuffle_epi8(g0,g1); + f1 = _mm256_cvtepi8_epi32(g1); + f2 = _mm256_mulhrs_epi16(f1,v); + f2 = _mm256_mullo_epi16(f2,p); + f1 = _mm256_add_epi32(f1,f2); + _mm256_storeu_si256((__m256i *)&r[ctr],f1); + ctr += _mm_popcnt_u32(good & 0xFF); + good >>= 8; + pos += 4; + + if(ctr > N - 8) break; + g0 = _mm256_extracti128_si256(f0,1); + g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); + g1 = _mm_shuffle_epi8(g0,g1); + f1 = _mm256_cvtepi8_epi32(g1); + f2 = _mm256_mulhrs_epi16(f1,v); + f2 = _mm256_mullo_epi16(f2,p); + f1 = _mm256_add_epi32(f1,f2); + _mm256_storeu_si256((__m256i *)&r[ctr],f1); + ctr += _mm_popcnt_u32(good & 0xFF); + good >>= 8; + pos += 4; + + if(ctr > N - 8) break; + g0 = _mm_bsrli_si128(g0,8); + g1 = _mm_loadl_epi64((__m128i *)&idxlut[good]); + g1 = _mm_shuffle_epi8(g0,g1); + f1 = _mm256_cvtepi8_epi32(g1); + f2 = _mm256_mulhrs_epi16(f1,v); + f2 = _mm256_mullo_epi16(f2,p); + f1 = _mm256_add_epi32(f1,f2); + _mm256_storeu_si256((__m256i *)&r[ctr],f1); + ctr += _mm_popcnt_u32(good); + pos += 4; + } + + uint32_t t0, t1; + while(ctr < N && pos < REJ_UNIFORM_ETA_BUFLEN) { + t0 = buf[pos] & 0x0F; + t1 = buf[pos++] >> 4; + + if(t0 < 15) { + t0 = t0 - (205*t0 >> 10)*5; + r[ctr++] = 2 - t0; + } + if(t1 < 15 && ctr < N) { + t1 = t1 - (205*t1 >> 10)*5; + r[ctr++] = 2 - t1; + } + } + + return ctr; +} + +#elif ETA == 4 +unsigned int rej_eta_avx(int32_t * restrict r, const uint8_t buf[REJ_UNIFORM_ETA_BUFLEN]) { + unsigned int ctr, pos; + uint32_t good; + __m256i f0, f1; + __m128i g0, g1; + const __m256i mask = _mm256_set1_epi8(15); + const __m256i eta = _mm256_set1_epi8(4); + const __m256i bound = _mm256_set1_epi8(9); + + ctr = pos = 0; + while(ctr <= N - 8 && pos <= REJ_UNIFORM_ETA_BUFLEN - 16) { + f0 = _mm256_cvtepu8_epi16(_mm_loadu_si128((__m128i *)&buf[pos])); + f1 = _mm256_slli_epi16(f0,4); + f0 = _mm256_or_si256(f0,f1); + f0 = _mm256_and_si256(f0,mask); + + f1 = _mm256_sub_epi8(f0,bound); + f0 = _mm256_sub_epi8(eta,f0); + good = _mm256_movemask_epi8(f1); + + g0 = _mm256_castsi256_si128(f0); + g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); + g1 = _mm_shuffle_epi8(g0,g1); + f1 = _mm256_cvtepi8_epi32(g1); + _mm256_storeu_si256((__m256i *)&r[ctr],f1); + ctr += _mm_popcnt_u32(good & 0xFF); + good >>= 8; + pos += 4; + + if(ctr > N - 8) break; + g0 = _mm_bsrli_si128(g0,8); + g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); + g1 = _mm_shuffle_epi8(g0,g1); + f1 = _mm256_cvtepi8_epi32(g1); + _mm256_storeu_si256((__m256i *)&r[ctr],f1); + ctr += _mm_popcnt_u32(good & 0xFF); + good >>= 8; + pos += 4; + + if(ctr > N - 8) break; + g0 = _mm256_extracti128_si256(f0,1); + g1 = _mm_loadl_epi64((__m128i *)&idxlut[good & 0xFF]); + g1 = _mm_shuffle_epi8(g0,g1); + f1 = _mm256_cvtepi8_epi32(g1); + _mm256_storeu_si256((__m256i *)&r[ctr],f1); + ctr += _mm_popcnt_u32(good & 0xFF); + good >>= 8; + pos += 4; + + if(ctr > N - 8) break; + g0 = _mm_bsrli_si128(g0,8); + g1 = _mm_loadl_epi64((__m128i *)&idxlut[good]); + g1 = _mm_shuffle_epi8(g0,g1); + f1 = _mm256_cvtepi8_epi32(g1); + _mm256_storeu_si256((__m256i *)&r[ctr],f1); + ctr += _mm_popcnt_u32(good); + pos += 4; + } + + uint32_t t0, t1; + while(ctr < N && pos < REJ_UNIFORM_ETA_BUFLEN) { + t0 = buf[pos] & 0x0F; + t1 = buf[pos++] >> 4; + + if(t0 < 9) + r[ctr++] = 4 - t0; + if(t1 < 9 && ctr < N) + r[ctr++] = 4 - t1; + } + + return ctr; +} +#endif diff --git a/avx2/rejsample.h b/avx2/rejsample.h new file mode 100644 index 0000000..61f3f35 --- /dev/null +++ b/avx2/rejsample.h @@ -0,0 +1,28 @@ +#ifndef REJSAMPLE_H +#define REJSAMPLE_H + +#include +#include "params.h" +#include "symmetric.h" + +#define REJ_UNIFORM_NBLOCKS ((768+STREAM128_BLOCKBYTES-1)/STREAM128_BLOCKBYTES) +#define REJ_UNIFORM_BUFLEN (REJ_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES) + +#if ETA == 2 +#define REJ_UNIFORM_ETA_NBLOCKS ((136+STREAM256_BLOCKBYTES-1)/STREAM256_BLOCKBYTES) +#elif ETA == 4 +#define REJ_UNIFORM_ETA_NBLOCKS ((227+STREAM256_BLOCKBYTES-1)/STREAM256_BLOCKBYTES) +#endif +#define REJ_UNIFORM_ETA_BUFLEN (REJ_UNIFORM_ETA_NBLOCKS*STREAM256_BLOCKBYTES) + +#define idxlut DILITHIUM_NAMESPACE(idxlut) +extern const uint8_t idxlut[256][8]; + +#define rej_uniform_avx DILITHIUM_NAMESPACE(rej_uniform_avx) +unsigned int rej_uniform_avx(int32_t *r, const uint8_t buf[REJ_UNIFORM_BUFLEN+8]); + +#define rej_eta_avx DILITHIUM_NAMESPACE(rej_eta_avx) +unsigned int rej_eta_avx(int32_t *r, const uint8_t buf[REJ_UNIFORM_ETA_BUFLEN]); + +#endif + diff --git a/avx2/rounding.c b/avx2/rounding.c new file mode 100644 index 0000000..3ada656 --- /dev/null +++ b/avx2/rounding.c @@ -0,0 +1,200 @@ +#include +#include +#include +#include "params.h" +#include "rounding.h" +#include "rejsample.h" +#include "consts.h" + +#define _mm256_blendv_epi32(a,b,mask) \ + _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(a), \ + _mm256_castsi256_ps(b), \ + _mm256_castsi256_ps(mask))) + +/************************************************* +* Name: power2round +* +* Description: For finite field elements a, compute a0, a1 such that +* a mod^+ Q = a1*2^D + a0 with -2^{D-1} < a0 <= 2^{D-1}. +* Assumes a to be positive standard representative. +* +* Arguments: - __m256i *a1: output array of length N/8 with high bits +* - __m256i *a0: output array of length N/8 with low bits a0 +* - const __m256i *a: input array of length N/8 +* +**************************************************/ +void power2round_avx(__m256i *a1, __m256i *a0, const __m256i *a) +{ + unsigned int i; + __m256i f,f0,f1; + const __m256i mask = _mm256_set1_epi32(-(1 << D)); + const __m256i half = _mm256_set1_epi32((1 << (D-1)) - 1); + + for(i = 0; i < N/8; ++i) { + f = _mm256_load_si256(&a[i]); + f1 = _mm256_add_epi32(f,half); + f0 = _mm256_and_si256(f1,mask); + f1 = _mm256_srli_epi32(f1,D); + f0 = _mm256_sub_epi32(f,f0); + _mm256_store_si256(&a1[i],f1); + _mm256_store_si256(&a0[i],f0); + } +} + +/************************************************* +* Name: decompose +* +* Description: For finite field element a, compute high and low parts a0, a1 such +* that a mod^+ Q = a1*ALPHA + a0 with -ALPHA/2 < a0 <= ALPHA/2 except +* if a1 = (Q-1)/ALPHA where we set a1 = 0 and +* -ALPHA/2 <= a0 = a mod Q - Q < 0. Assumes a to be positive standard +* representative. +* +* Arguments: - __m256i *a1: output array of length N/8 with high parts +* - __m256i *a0: output array of length N/8 with low parts a0 +* - const __m256i *a: input array of length N/8 +* +**************************************************/ +#if GAMMA2 == (Q-1)/32 +void decompose_avx(__m256i *a1, __m256i *a0, const __m256i *a) +{ + unsigned int i; + __m256i f,f0,f1; + const __m256i q = _mm256_load_si256(&qdata.vec[_8XQ/8]); + const __m256i hq = _mm256_srli_epi32(q,1); + const __m256i v = _mm256_set1_epi32(1025); + const __m256i alpha = _mm256_set1_epi32(2*GAMMA2); + const __m256i off = _mm256_set1_epi32(127); + const __m256i shift = _mm256_set1_epi32(512); + const __m256i mask = _mm256_set1_epi32(15); + + for(i=0;i +#include +#include "params.h" + +#define power2round_avx DILITHIUM_NAMESPACE(power2round_avx) +void power2round_avx(__m256i *a1, __m256i *a0, const __m256i *a); +#define decompose_avx DILITHIUM_NAMESPACE(decompose_avx) +void decompose_avx(__m256i *a1, __m256i *a0, const __m256i *a); +#define make_hint_avx DILITHIUM_NAMESPACE(make_hint_avx) +unsigned int make_hint_avx(uint8_t hint[N], const __m256i *a0, const __m256i *a1); +#define use_hint_avx DILITHIUM_NAMESPACE(use_hint_avx) +void use_hint_avx(__m256i *b, const __m256i *a, const __m256i *hint); + +#endif diff --git a/avx2/shuffle.S b/avx2/shuffle.S new file mode 100644 index 0000000..08c757c --- /dev/null +++ b/avx2/shuffle.S @@ -0,0 +1,54 @@ +#include "consts.h" +.include "shuffle.inc" + +.text +nttunpack128_avx: +#load +vmovdqa (%rdi),%ymm4 +vmovdqa 32(%rdi),%ymm5 +vmovdqa 64(%rdi),%ymm6 +vmovdqa 96(%rdi),%ymm7 +vmovdqa 128(%rdi),%ymm8 +vmovdqa 160(%rdi),%ymm9 +vmovdqa 192(%rdi),%ymm10 +vmovdqa 224(%rdi),%ymm11 + +shuffle8 4,8,3,8 +shuffle8 5,9,4,9 +shuffle8 6,10,5,10 +shuffle8 7,11,6,11 + +shuffle4 3,5,7,5 +shuffle4 8,10,3,10 +shuffle4 4,6,8,6 +shuffle4 9,11,4,11 + +shuffle2 7,8,9,8 +shuffle2 5,6,7,6 +shuffle2 3,4,5,4 +shuffle2 10,11,3,11 + +#store +vmovdqa %ymm9,(%rdi) +vmovdqa %ymm8,32(%rdi) +vmovdqa %ymm7,64(%rdi) +vmovdqa %ymm6,96(%rdi) +vmovdqa %ymm5,128(%rdi) +vmovdqa %ymm4,160(%rdi) +vmovdqa %ymm3,192(%rdi) +vmovdqa %ymm11,224(%rdi) + +ret + +.global cdecl(nttunpack_avx) +cdecl(nttunpack_avx): +call nttunpack128_avx +add $256,%rdi +call nttunpack128_avx +add $256,%rdi +call nttunpack128_avx +add $256,%rdi +call nttunpack128_avx +ret + +.section .note.GNU-stack,"",@progbits diff --git a/avx2/shuffle.inc b/avx2/shuffle.inc new file mode 100644 index 0000000..73e9ffe --- /dev/null +++ b/avx2/shuffle.inc @@ -0,0 +1,25 @@ +.macro shuffle8 r0,r1,r2,r3 +vperm2i128 $0x20,%ymm\r1,%ymm\r0,%ymm\r2 +vperm2i128 $0x31,%ymm\r1,%ymm\r0,%ymm\r3 +.endm + +.macro shuffle4 r0,r1,r2,r3 +vpunpcklqdq %ymm\r1,%ymm\r0,%ymm\r2 +vpunpckhqdq %ymm\r1,%ymm\r0,%ymm\r3 +.endm + +.macro shuffle2 r0,r1,r2,r3 +#vpsllq $32,%ymm\r1,%ymm\r2 +vmovsldup %ymm\r1,%ymm\r2 +vpblendd $0xAA,%ymm\r2,%ymm\r0,%ymm\r2 +vpsrlq $32,%ymm\r0,%ymm\r0 +#vmovshdup %ymm\r0,%ymm\r0 +vpblendd $0xAA,%ymm\r1,%ymm\r0,%ymm\r3 +.endm + +.macro shuffle1 r0,r1,r2,r3 +vpslld $16,%ymm\r1,%ymm\r2 +vpblendw $0xAA,%ymm\r2,%ymm\r0,%ymm\r2 +vpsrld $16,%ymm\r0,%ymm\r0 +vpblendw $0xAA,%ymm\r1,%ymm\r0,%ymm\r3 +.endm diff --git a/avx2/sign.c b/avx2/sign.c new file mode 100644 index 0000000..efb6ea3 --- /dev/null +++ b/avx2/sign.c @@ -0,0 +1,530 @@ +#include +#include +#include "align.h" +#include "params.h" +#include "sign.h" +#include "packing.h" +#include "polyvec.h" +#include "poly.h" +#include "randombytes.h" +#include "symmetric.h" +#include "fips202.h" + +static inline void polyvec_matrix_expand_row(polyvecl **row, polyvecl buf[2], const uint8_t rho[SEEDBYTES], unsigned int i) { + switch(i) { + case 0: + polyvec_matrix_expand_row0(buf, buf + 1, rho); + *row = buf; + break; + case 1: + polyvec_matrix_expand_row1(buf + 1, buf, rho); + *row = buf + 1; + break; + case 2: + polyvec_matrix_expand_row2(buf, buf + 1, rho); + *row = buf; + break; + case 3: + polyvec_matrix_expand_row3(buf + 1, buf, rho); + *row = buf + 1; + break; +#if K > 4 + case 4: + polyvec_matrix_expand_row4(buf, buf + 1, rho); + *row = buf; + break; + case 5: + polyvec_matrix_expand_row5(buf + 1, buf, rho); + *row = buf + 1; + break; +#endif +#if K > 6 + case 6: + polyvec_matrix_expand_row6(buf, buf + 1, rho); + *row = buf; + break; + case 7: + polyvec_matrix_expand_row7(buf + 1, buf, rho); + *row = buf + 1; + break; +#endif + } +} + +/************************************************* +* Name: crypto_sign_keypair +* +* Description: Generates public and private key. +* +* Arguments: - uint8_t *pk: pointer to output public key (allocated +* array of CRYPTO_PUBLICKEYBYTES bytes) +* - uint8_t *sk: pointer to output private key (allocated +* array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + unsigned int i; + uint8_t seedbuf[2*SEEDBYTES + CRHBYTES]; + const uint8_t *rho, *rhoprime, *key; + polyvecl rowbuf[2]; + polyvecl s1, *row = rowbuf; + polyveck s2; + poly t1, t0; + + /* Get randomness for rho, rhoprime and key */ + randombytes(seedbuf, SEEDBYTES); + seedbuf[SEEDBYTES+0] = K; + seedbuf[SEEDBYTES+1] = L; + shake256(seedbuf, 2*SEEDBYTES + CRHBYTES, seedbuf, SEEDBYTES+2); + rho = seedbuf; + rhoprime = rho + SEEDBYTES; + key = rhoprime + CRHBYTES; + + /* Store rho, key */ + memcpy(pk, rho, SEEDBYTES); + memcpy(sk, rho, SEEDBYTES); + memcpy(sk + SEEDBYTES, key, SEEDBYTES); + + /* Sample short vectors s1 and s2 */ +#if K == 4 && L == 4 + poly_uniform_eta_4x(&s1.vec[0], &s1.vec[1], &s1.vec[2], &s1.vec[3], rhoprime, 0, 1, 2, 3); + poly_uniform_eta_4x(&s2.vec[0], &s2.vec[1], &s2.vec[2], &s2.vec[3], rhoprime, 4, 5, 6, 7); +#elif K == 6 && L == 5 + poly_uniform_eta_4x(&s1.vec[0], &s1.vec[1], &s1.vec[2], &s1.vec[3], rhoprime, 0, 1, 2, 3); + poly_uniform_eta_4x(&s1.vec[4], &s2.vec[0], &s2.vec[1], &s2.vec[2], rhoprime, 4, 5, 6, 7); + poly_uniform_eta_4x(&s2.vec[3], &s2.vec[4], &s2.vec[5], &t0, rhoprime, 8, 9, 10, 11); +#elif K == 8 && L == 7 + poly_uniform_eta_4x(&s1.vec[0], &s1.vec[1], &s1.vec[2], &s1.vec[3], rhoprime, 0, 1, 2, 3); + poly_uniform_eta_4x(&s1.vec[4], &s1.vec[5], &s1.vec[6], &s2.vec[0], rhoprime, 4, 5, 6, 7); + poly_uniform_eta_4x(&s2.vec[1], &s2.vec[2], &s2.vec[3], &s2.vec[4], rhoprime, 8, 9, 10, 11); + poly_uniform_eta_4x(&s2.vec[5], &s2.vec[6], &s2.vec[7], &t0, rhoprime, 12, 13, 14, 15); +#else +#error +#endif + + /* Pack secret vectors */ + for(i = 0; i < L; i++) + polyeta_pack(sk + 2*SEEDBYTES + TRBYTES + i*POLYETA_PACKEDBYTES, &s1.vec[i]); + for(i = 0; i < K; i++) + polyeta_pack(sk + 2*SEEDBYTES + TRBYTES + (L + i)*POLYETA_PACKEDBYTES, &s2.vec[i]); + + /* Transform s1 */ + polyvecl_ntt(&s1); + + for(i = 0; i < K; i++) { + /* Expand matrix row */ + polyvec_matrix_expand_row(&row, rowbuf, rho, i); + + /* Compute inner-product */ + polyvecl_pointwise_acc_montgomery(&t1, row, &s1); + poly_invntt_tomont(&t1); + + /* Add error polynomial */ + poly_add(&t1, &t1, &s2.vec[i]); + + /* Round t and pack t1, t0 */ + poly_caddq(&t1); + poly_power2round(&t1, &t0, &t1); + polyt1_pack(pk + SEEDBYTES + i*POLYT1_PACKEDBYTES, &t1); + polyt0_pack(sk + 2*SEEDBYTES + TRBYTES + (L+K)*POLYETA_PACKEDBYTES + i*POLYT0_PACKEDBYTES, &t0); + } + + /* Compute H(rho, t1) and store in secret key */ + shake256(sk + 2*SEEDBYTES, TRBYTES, pk, CRYPTO_PUBLICKEYBYTES); + + return 0; +} + +/************************************************* +* Name: crypto_sign_signature_internal +* +* Description: Computes signature. Internal API. +* +* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES) +* - size_t *siglen: pointer to output length of signature +* - uint8_t *m: pointer to message to be signed +* - size_t mlen: length of message +* - uint8_t *pre: pointer to prefix string +* - size_t prelen: length of prefix string +* - uint8_t *rnd: pointer to random seed +* - uint8_t *sk: pointer to bit-packed secret key +* +* Returns 0 (success) +**************************************************/ +int crypto_sign_signature_internal(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, + const uint8_t *pre, size_t prelen, const uint8_t rnd[RNDBYTES], const uint8_t *sk) +{ + unsigned int i, n, pos; + uint8_t seedbuf[2*SEEDBYTES + TRBYTES + 2*CRHBYTES]; + uint8_t *rho, *tr, *key, *mu, *rhoprime; + uint8_t hintbuf[N]; + uint8_t *hint = sig + CTILDEBYTES + L*POLYZ_PACKEDBYTES; + uint64_t nonce = 0; + polyvecl mat[K], s1, z; + polyveck t0, s2, w1; + poly c, tmp; + union { + polyvecl y; + polyveck w0; + } tmpv; + keccak_state state; + + rho = seedbuf; + tr = rho + SEEDBYTES; + key = tr + TRBYTES; + mu = key + SEEDBYTES; + rhoprime = mu + CRHBYTES; + unpack_sk(rho, tr, key, &t0, &s1, &s2, sk); + + /* Compute mu = CRH(tr, pre, msg) */ + shake256_init(&state); + shake256_absorb(&state, tr, TRBYTES); + shake256_absorb(&state, pre, prelen); + shake256_absorb(&state, m, mlen); + shake256_finalize(&state); + shake256_squeeze(mu, CRHBYTES, &state); + + /* Compute rhoprime = CRH(key, rnd, mu) */ + shake256_init(&state); + shake256_absorb(&state, key, SEEDBYTES); + shake256_absorb(&state, rnd, RNDBYTES); + shake256_absorb(&state, mu, CRHBYTES); + shake256_finalize(&state); + shake256_squeeze(rhoprime, CRHBYTES, &state); + + /* Expand matrix and transform vectors */ + polyvec_matrix_expand(mat, rho); + polyvecl_ntt(&s1); + polyveck_ntt(&s2); + polyveck_ntt(&t0); + +rej: + /* Sample intermediate vector y */ +#if L == 4 + poly_uniform_gamma1_4x(&z.vec[0], &z.vec[1], &z.vec[2], &z.vec[3], + rhoprime, nonce, nonce + 1, nonce + 2, nonce + 3); + nonce += 4; +#elif L == 5 + poly_uniform_gamma1_4x(&z.vec[0], &z.vec[1], &z.vec[2], &z.vec[3], + rhoprime, nonce, nonce + 1, nonce + 2, nonce + 3); + poly_uniform_gamma1(&z.vec[4], rhoprime, nonce + 4); + nonce += 5; +#elif L == 7 + poly_uniform_gamma1_4x(&z.vec[0], &z.vec[1], &z.vec[2], &z.vec[3], + rhoprime, nonce, nonce + 1, nonce + 2, nonce + 3); + poly_uniform_gamma1_4x(&z.vec[4], &z.vec[5], &z.vec[6], &tmp, + rhoprime, nonce + 4, nonce + 5, nonce + 6, 0); + nonce += 7; +#else +#error +#endif + + /* Matrix-vector product */ + tmpv.y = z; + polyvecl_ntt(&tmpv.y); + polyvec_matrix_pointwise_montgomery(&w1, mat, &tmpv.y); + polyveck_invntt_tomont(&w1); + + /* Decompose w and call the random oracle */ + polyveck_caddq(&w1); + polyveck_decompose(&w1, &tmpv.w0, &w1); + polyveck_pack_w1(sig, &w1); + + shake256_init(&state); + shake256_absorb(&state, mu, CRHBYTES); + shake256_absorb(&state, sig, K*POLYW1_PACKEDBYTES); + shake256_finalize(&state); + shake256_squeeze(sig, CTILDEBYTES, &state); + poly_challenge(&c, sig); + poly_ntt(&c); + + /* Compute z, reject if it reveals secret */ + for(i = 0; i < L; i++) { + poly_pointwise_montgomery(&tmp, &c, &s1.vec[i]); + poly_invntt_tomont(&tmp); + poly_add(&z.vec[i], &z.vec[i], &tmp); + poly_reduce(&z.vec[i]); + if(poly_chknorm(&z.vec[i], GAMMA1 - BETA)) + goto rej; + } + + /* Zero hint vector in signature */ + pos = 0; + memset(hint, 0, OMEGA); + + for(i = 0; i < K; i++) { + /* Check that subtracting cs2 does not change high bits of w and low bits + * do not reveal secret information */ + poly_pointwise_montgomery(&tmp, &c, &s2.vec[i]); + poly_invntt_tomont(&tmp); + poly_sub(&tmpv.w0.vec[i], &tmpv.w0.vec[i], &tmp); + poly_reduce(&tmpv.w0.vec[i]); + if(poly_chknorm(&tmpv.w0.vec[i], GAMMA2 - BETA)) + goto rej; + + /* Compute hints */ + poly_pointwise_montgomery(&tmp, &c, &t0.vec[i]); + poly_invntt_tomont(&tmp); + poly_reduce(&tmp); + if(poly_chknorm(&tmp, GAMMA2)) + goto rej; + + poly_add(&tmpv.w0.vec[i], &tmpv.w0.vec[i], &tmp); + n = poly_make_hint(hintbuf, &tmpv.w0.vec[i], &w1.vec[i]); + if(pos + n > OMEGA) + goto rej; + + /* Store hints in signature */ + memcpy(&hint[pos], hintbuf, n); + hint[OMEGA + i] = pos = pos + n; + } + + /* Pack z into signature */ + for(i = 0; i < L; i++) + polyz_pack(sig + CTILDEBYTES + i*POLYZ_PACKEDBYTES, &z.vec[i]); + + *siglen = CRYPTO_BYTES; + return 0; +} + +/************************************************* +* Name: crypto_sign_signature +* +* Description: Computes signature. +* +* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES) +* - size_t *siglen: pointer to output length of signature +* - uint8_t *m: pointer to message to be signed +* - size_t mlen: length of message +* - uint8_t *ctx: pointer to context string +* - size_t ctxlen: length of context string +* - uint8_t *sk: pointer to bit-packed secret key +* +* Returns 0 (success) or -1 (context string too long) +**************************************************/ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, const uint8_t *sk) +{ + uint8_t pre[257]; + uint8_t rnd[RNDBYTES]; + + if(ctxlen > 255) + return -1; + + /* Prepare pre = (0, ctxlen, ctx) */ + pre[0] = 0; + pre[1] = ctxlen; + memcpy(&pre[2], ctx, ctxlen); + +#ifdef DILITHIUM_RANDOMIZED_SIGNING + randombytes(rnd, RNDBYTES); +#else + memset(rnd, 0, RNDBYTES); +#endif + + crypto_sign_signature_internal(sig,siglen,m,mlen,pre,2+ctxlen,rnd,sk); + return 0; +} + +/************************************************* +* Name: crypto_sign +* +* Description: Compute signed message. +* +* Arguments: - uint8_t *sm: pointer to output signed message (allocated +* array with CRYPTO_BYTES + mlen bytes), +* can be equal to m +* - size_t *smlen: pointer to output length of signed +* message +* - const uint8_t *m: pointer to message to be signed +* - size_t mlen: length of message +* - const uint8_t *ctx: pointer to context string +* - size_t ctxlen: length of context string +* - const uint8_t *sk: pointer to bit-packed secret key +* +* Returns 0 (success) +**************************************************/ +int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk) +{ + size_t i; + int ret; + + for(i = 0; i < mlen; ++i) + sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + ret = crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, ctx, ctxlen, sk); + *smlen += mlen; + return ret; +} + +/************************************************* +* Name: crypto_sign_verify_internal +* +* Description: Verifies signature. Internal API. +* +* Arguments: - uint8_t *m: pointer to input signature +* - size_t siglen: length of signature +* - const uint8_t *m: pointer to message +* - size_t mlen: length of message +* - const uint8_t *pre: pointer to prefix string +* - size_t prelen: length of prefix string +* - const uint8_t *pk: pointer to bit-packed public key +* +* Returns 0 if signature could be verified correctly and -1 otherwise +**************************************************/ +int crypto_sign_verify_internal(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, + const uint8_t *pre, size_t prelen, const uint8_t *pk) { + unsigned int i, j, pos = 0; + /* polyw1_pack writes additional 14 bytes */ + ALIGNED_UINT8(K*POLYW1_PACKEDBYTES+14) buf; + uint8_t mu[CRHBYTES]; + const uint8_t *hint = sig + CTILDEBYTES + L*POLYZ_PACKEDBYTES; + polyvecl rowbuf[2]; + polyvecl *row = rowbuf; + polyvecl z; + poly c, w1, h; + keccak_state state; + + if(siglen != CRYPTO_BYTES) + return -1; + + /* Compute CRH(H(rho, t1), pre, msg) */ + shake256(mu, TRBYTES, pk, CRYPTO_PUBLICKEYBYTES); + shake256_init(&state); + shake256_absorb(&state, mu, CRHBYTES); + shake256_absorb(&state, pre, prelen); + shake256_absorb(&state, m, mlen); + shake256_finalize(&state); + shake256_squeeze(mu, CRHBYTES, &state); + + /* Expand challenge */ + poly_challenge(&c, sig); + poly_ntt(&c); + + /* Unpack z; shortness follows from unpacking */ + for(i = 0; i < L; i++) { + polyz_unpack(&z.vec[i], sig + CTILDEBYTES + i*POLYZ_PACKEDBYTES); + poly_ntt(&z.vec[i]); + } + + for(i = 0; i < K; i++) { + /* Expand matrix row */ + polyvec_matrix_expand_row(&row, rowbuf, pk, i); + + /* Compute i-th row of Az - c2^Dt1 */ + polyvecl_pointwise_acc_montgomery(&w1, row, &z); + + polyt1_unpack(&h, pk + SEEDBYTES + i*POLYT1_PACKEDBYTES); + poly_shiftl(&h); + poly_ntt(&h); + poly_pointwise_montgomery(&h, &c, &h); + + poly_sub(&w1, &w1, &h); + poly_reduce(&w1); + poly_invntt_tomont(&w1); + + /* Get hint polynomial and reconstruct w1 */ + memset(h.vec, 0, sizeof(poly)); + if(hint[OMEGA + i] < pos || hint[OMEGA + i] > OMEGA) + return -1; + + for(j = pos; j < hint[OMEGA + i]; ++j) { + /* Coefficients are ordered for strong unforgeability */ + if(j > pos && hint[j] <= hint[j-1]) return -1; + h.coeffs[hint[j]] = 1; + } + pos = hint[OMEGA + i]; + + poly_caddq(&w1); + poly_use_hint(&w1, &w1, &h); + polyw1_pack(buf.coeffs + i*POLYW1_PACKEDBYTES, &w1); + } + + /* Extra indices are zero for strong unforgeability */ + for(j = pos; j < OMEGA; ++j) + if(hint[j]) return -1; + + /* Call random oracle and verify challenge */ + shake256_init(&state); + shake256_absorb(&state, mu, CRHBYTES); + shake256_absorb(&state, buf.coeffs, K*POLYW1_PACKEDBYTES); + shake256_finalize(&state); + shake256_squeeze(buf.coeffs, CTILDEBYTES, &state); + for(i = 0; i < CTILDEBYTES; ++i) + if(buf.coeffs[i] != sig[i]) + return -1; + + return 0; +} + +/************************************************* +* Name: crypto_sign_verify +* +* Description: Verifies signature. +* +* Arguments: - uint8_t *m: pointer to input signature +* - size_t siglen: length of signature +* - const uint8_t *m: pointer to message +* - size_t mlen: length of message +* - const uint8_t *ctx: pointer to context string +* - size_t ctxlen: length of context string +* - const uint8_t *pk: pointer to bit-packed public key +* +* Returns 0 if signature could be verified correctly and -1 otherwise +**************************************************/ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, const uint8_t *pk) +{ + uint8_t pre[257]; + + if(ctxlen > 255) + return -1; + + pre[0] = 0; + pre[1] = ctxlen; + memcpy(&pre[2], ctx, ctxlen); + return crypto_sign_verify_internal(sig,siglen,m,mlen,pre,2+ctxlen,pk); +} + +/************************************************* +* Name: crypto_sign_open +* +* Description: Verify signed message. +* +* Arguments: - uint8_t *m: pointer to output message (allocated +* array with smlen bytes), can be equal to sm +* - size_t *mlen: pointer to output length of message +* - const uint8_t *sm: pointer to signed message +* - size_t smlen: length of signed message +* - const uint8_t *ctx: pointer to context string +* - size_t ctxlen: length of context string +* - const uint8_t *pk: pointer to bit-packed public key +* +* Returns 0 if signed message could be verified correctly and -1 otherwise +**************************************************/ +int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, + const uint8_t *ctx, size_t ctxlen, const uint8_t *pk) { + size_t i; + + if(smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + if(crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, ctx, ctxlen, pk)) + goto badsig; + else { + /* All good, copy msg, return 0 */ + for(i = 0; i < *mlen; ++i) + m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = 0; + for(i = 0; i < smlen; ++i) + m[i] = 0; + + return -1; +} diff --git a/avx2/sign.h b/avx2/sign.h new file mode 120000 index 0000000..200b72f --- /dev/null +++ b/avx2/sign.h @@ -0,0 +1 @@ +../ref/sign.h \ No newline at end of file diff --git a/avx2/symmetric-shake.c b/avx2/symmetric-shake.c new file mode 120000 index 0000000..86f8b6c --- /dev/null +++ b/avx2/symmetric-shake.c @@ -0,0 +1 @@ +../ref/symmetric-shake.c \ No newline at end of file diff --git a/avx2/symmetric.h b/avx2/symmetric.h new file mode 100644 index 0000000..8f3c3c5 --- /dev/null +++ b/avx2/symmetric.h @@ -0,0 +1,26 @@ +#ifndef SYMMETRIC_H +#define SYMMETRIC_H + +#include +#include "params.h" + +#include "fips202.h" + +typedef keccak_state stream128_state; +typedef keccak_state stream256_state; + +#define dilithium_shake128_stream_init DILITHIUM_NAMESPACE(dilithium_shake128_stream_init) +void dilithium_shake128_stream_init(keccak_state *state, const uint8_t seed[SEEDBYTES], uint16_t nonce); + +#define dilithium_shake256_stream_init DILITHIUM_NAMESPACE(dilithium_shake256_stream_init) +void dilithium_shake256_stream_init(keccak_state *state, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define STREAM128_BLOCKBYTES SHAKE128_RATE +#define STREAM256_BLOCKBYTES SHAKE256_RATE + +#define stream128_init(STATE, SEED, NONCE) dilithium_shake128_stream_init(STATE, SEED, NONCE) +#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) shake128_squeezeblocks(OUT, OUTBLOCKS, STATE) +#define stream256_init(STATE, SEED, NONCE) dilithium_shake256_stream_init(STATE, SEED, NONCE) +#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) + +#endif diff --git a/avx2/test/.gitignore b/avx2/test/.gitignore new file mode 100644 index 0000000..99b3f73 --- /dev/null +++ b/avx2/test/.gitignore @@ -0,0 +1,10 @@ +test_dilithium2 +test_dilithium3 +test_dilithium5 +test_vectors2 +test_vectors3 +test_vectors5 +test_speed2 +test_speed3 +test_speed5 +test_mul diff --git a/avx2/test/cpucycles.c b/avx2/test/cpucycles.c new file mode 120000 index 0000000..4d6fc8a --- /dev/null +++ b/avx2/test/cpucycles.c @@ -0,0 +1 @@ +../../ref/test/cpucycles.c \ No newline at end of file diff --git a/avx2/test/cpucycles.h b/avx2/test/cpucycles.h new file mode 120000 index 0000000..269feb3 --- /dev/null +++ b/avx2/test/cpucycles.h @@ -0,0 +1 @@ +../../ref/test/cpucycles.h \ No newline at end of file diff --git a/avx2/test/speed_print.c b/avx2/test/speed_print.c new file mode 120000 index 0000000..98f2a46 --- /dev/null +++ b/avx2/test/speed_print.c @@ -0,0 +1 @@ +../../ref/test/speed_print.c \ No newline at end of file diff --git a/avx2/test/speed_print.h b/avx2/test/speed_print.h new file mode 120000 index 0000000..8ba4e5e --- /dev/null +++ b/avx2/test/speed_print.h @@ -0,0 +1 @@ +../../ref/test/speed_print.h \ No newline at end of file diff --git a/avx2/test/test_dilithium.c b/avx2/test/test_dilithium.c new file mode 120000 index 0000000..729cb5b --- /dev/null +++ b/avx2/test/test_dilithium.c @@ -0,0 +1 @@ +../../ref/test/test_dilithium.c \ No newline at end of file diff --git a/avx2/test/test_mul.c b/avx2/test/test_mul.c new file mode 120000 index 0000000..013f7af --- /dev/null +++ b/avx2/test/test_mul.c @@ -0,0 +1 @@ +../../ref/test/test_mul.c \ No newline at end of file diff --git a/avx2/test/test_speed.c b/avx2/test/test_speed.c new file mode 120000 index 0000000..7decc02 --- /dev/null +++ b/avx2/test/test_speed.c @@ -0,0 +1 @@ +../../ref/test/test_speed.c \ No newline at end of file diff --git a/avx2/test/test_vectors.c b/avx2/test/test_vectors.c new file mode 100644 index 0000000..430ff2a --- /dev/null +++ b/avx2/test/test_vectors.c @@ -0,0 +1,275 @@ +#include +#include +#include +#include +#include "../randombytes.h" +#include "../fips202.h" +#include "../params.h" +#include "../sign.h" +#include "../poly.h" +#include "../polyvec.h" +#include "../packing.h" + +#define MLEN 32 +#define CTXLEN 13 +#define NVECTORS 10000 + +static unsigned int nttidx(unsigned int k) { + unsigned int r; + r = k/64*64; + k %= 64; + r += k/8; + k %= 8; + r += k*8; + return r; +} + +/* Initital state after absorbing empty string + * Permute before squeeze is achieved by setting pos to SHAKE128_RATE */ +static keccak_state rngstate = {{0x1F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (1ULL << 63), 0, 0, 0, 0}, SHAKE128_RATE}; + +void randombytes(uint8_t *x,size_t xlen) { + shake128_squeeze(x, xlen, &rngstate); +} + +int main(void) { + unsigned int i, j, k, l; + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t sig[CRYPTO_BYTES]; + uint8_t m[MLEN]; + uint8_t ctx[CTXLEN] = {0}; + uint8_t seed[CRHBYTES]; + uint8_t buf[CRYPTO_SECRETKEYBYTES]; + size_t siglen; + poly c, tmp; + polyvecl s, y, mat[K]; + polyveck w, w1, w0, t1, t0; + + snprintf((char*)ctx,CTXLEN,"test_vectors"); + + for(i = 0; i < NVECTORS; ++i) { + printf("count = %u\n", i); + + randombytes(m, MLEN); + printf("m = "); + for(j = 0; j < MLEN; ++j) + printf("%02x", m[j]); + printf("\n"); + + crypto_sign_keypair(pk, sk); + shake256(buf, 32, pk, CRYPTO_PUBLICKEYBYTES); + printf("pk = "); + for(j = 0; j < 32; ++j) + printf("%02x", buf[j]); + printf("\n"); + shake256(buf, 32, sk, CRYPTO_SECRETKEYBYTES); + printf("sk = "); + for(j = 0; j < 32; ++j) + printf("%02x", buf[j]); + printf("\n"); + + crypto_sign_signature(sig, &siglen, m, MLEN, ctx, CTXLEN, sk); + shake256(buf, 32, sig, CRYPTO_BYTES); + printf("sig = "); + for(j = 0; j < 32; ++j) + printf("%02x", buf[j]); + printf("\n"); + + if(crypto_sign_verify(sig, siglen, m, MLEN, ctx, CTXLEN, pk)) + fprintf(stderr,"Signature verification failed!\n"); + + randombytes(seed, sizeof(seed)); + printf("seed = "); + for(j = 0; j < sizeof(seed); ++j) + printf("%02X", seed[j]); + printf("\n"); + + polyvec_matrix_expand(mat, seed); + printf("A = (["); + for(j = 0; j < K; ++j) { + for(k = 0; k < L; ++k) { + for(l = 0; l < N; ++l) { + printf("%8d", mat[j].vec[k].coeffs[nttidx(l)]); + if(l < N-1) printf(", "); + else if(k < L-1) printf("], ["); + else if(j < K-1) printf("];\n ["); + else printf("])\n"); + } + } + } + + +#if L == 4 + poly_uniform_eta_4x(&s.vec[0], &s.vec[1], &s.vec[2], &s.vec[3], seed, 0, 1, 2, 3); +#elif L == 5 + poly_uniform_eta_4x(&s.vec[0], &s.vec[1], &s.vec[2], &s.vec[3], seed, 0, 1, 2, 3); + poly_uniform_eta(&s.vec[4], seed, 4); +#elif L == 7 + poly_uniform_eta_4x(&s.vec[0], &s.vec[1], &s.vec[2], &s.vec[3], seed, 0, 1, 2, 3); + poly_uniform_eta_4x(&s.vec[4], &s.vec[5], &s.vec[6], &tmp, seed, 4, 5, 6, 7); +#else +#error +#endif + + polyeta_pack(buf, &s.vec[0]); + polyeta_unpack(&tmp, buf); + for(j = 0; j < N; ++j) + if(tmp.coeffs[j] != s.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in polyeta_(un)pack!\n"); + + if(polyvecl_chknorm(&s, ETA+1)) + fprintf(stderr, "ERROR in polyvecl_chknorm(&s ,ETA+1)!\n"); + + printf("s = (["); + for(j = 0; j < L; ++j) { + for(k = 0; k < N; ++k) { + printf("%3d", s.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < L-1) printf("],\n ["); + else printf("])\n"); + } + } + +#if L == 4 + poly_uniform_gamma1_4x(&y.vec[0], &y.vec[1], &y.vec[2], &y.vec[3], seed, 0, 1, 2, 3); +#elif L == 5 + poly_uniform_gamma1_4x(&y.vec[0], &y.vec[1], &y.vec[2], &y.vec[3], seed, 0, 1, 2, 3); + poly_uniform_gamma1(&y.vec[4], seed, 4); +#elif L == 7 + poly_uniform_gamma1_4x(&y.vec[0], &y.vec[1], &y.vec[2], &y.vec[3], seed, 0, 1, 2, 3); + poly_uniform_gamma1_4x(&y.vec[4], &y.vec[5], &y.vec[6], &tmp, seed, 4, 5, 6, 7); +#else +#error +#endif + + polyz_pack(buf, &y.vec[0]); + polyz_unpack(&tmp, buf); + for(j = 0; j < N; ++j) + if(tmp.coeffs[j] != y.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in polyz_(un)pack!\n"); + + if(polyvecl_chknorm(&y, GAMMA1+1)) + fprintf(stderr, "ERROR in polyvecl_chknorm(&y, GAMMA1)!\n"); + + printf("y = (["); + for(j = 0; j < L; ++j) { + for(k = 0; k < N; ++k) { + printf("%8d", y.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < L-1) printf("],\n ["); + else printf("])\n"); + } + } + + polyvecl_ntt(&y); + polyvec_matrix_pointwise_montgomery(&w, mat, &y); + polyveck_invntt_tomont(&w); + polyveck_caddq(&w); + polyveck_decompose(&w1, &w0, &w); + + for(j = 0; j < N; ++j) { + tmp.coeffs[j] = w1.vec[0].coeffs[j]*2*GAMMA2 + w0.vec[0].coeffs[j]; + if(tmp.coeffs[j] < 0) tmp.coeffs[j] += Q; + if(tmp.coeffs[j] != w.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in poly_decompose!\n"); + } + + polyw1_pack(buf, &w1.vec[0]); +#if GAMMA2 == (Q-1)/32 + for(j = 0; j < N/2; ++j) { + tmp.coeffs[2*j+0] = buf[j] & 0xF; + tmp.coeffs[2*j+1] = buf[j] >> 4; + if(tmp.coeffs[2*j+0] != w1.vec[0].coeffs[2*j+0] + || tmp.coeffs[2*j+1] != w1.vec[0].coeffs[2*j+1]) + fprintf(stderr, "ERROR in polyw1_pack!\n"); + } +#endif + +#if GAMMA2 == (Q-1)/32 + if(polyveck_chknorm(&w1, 16)) + fprintf(stderr, "ERROR in polyveck_chknorm(&w1, 16)!\n"); +#elif GAMMA2 == (Q-1)/88 + if(polyveck_chknorm(&w1, 44)) + fprintf(stderr, "ERROR in polyveck_chknorm(&w1, 44)!\n"); +#endif + if(polyveck_chknorm(&w0, GAMMA2 + 1)) + fprintf(stderr, "ERROR in polyveck_chknorm(&w0, GAMMA2+1)!\n"); + + printf("w1 = (["); + for(j = 0; j < K; ++j) { + for(k = 0; k < N; ++k) { + printf("%2d", w1.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < K-1) printf("],\n ["); + else printf("])\n"); + } + } + printf("w0 = (["); + for(j = 0; j < K; ++j) { + for(k = 0; k < N; ++k) { + printf("%8d", w0.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < K-1) printf("],\n ["); + else printf("])\n"); + } + } + + polyveck_power2round(&t1, &t0, &w); + + for(j = 0; j < N; ++j) { + tmp.coeffs[j] = (t1.vec[0].coeffs[j] << D) + t0.vec[0].coeffs[j]; + if(tmp.coeffs[j] != w.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in poly_power2round!\n"); + } + + polyt1_pack(buf, &t1.vec[0]); + polyt1_unpack(&tmp, buf); + for(j = 0; j < N; ++j) { + if(tmp.coeffs[j] != t1.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in polyt1_(un)pack!\n"); + } + polyt0_pack(buf, &t0.vec[0]); + polyt0_unpack(&tmp, buf); + for(j = 0; j < N; ++j) { + if(tmp.coeffs[j] != t0.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in polyt0_(un)pack!\n"); + } + + if(polyveck_chknorm(&t1, 1024)) + fprintf(stderr, "ERROR in polyveck_chknorm(&t1, 1024)!\n"); + if(polyveck_chknorm(&t0, (1U << (D-1)) + 1)) + fprintf(stderr, "ERROR in polyveck_chknorm(&t0, (1 << (D-1)) + 1)!\n"); + + printf("t1 = (["); + for(j = 0; j < K; ++j) { + for(k = 0; k < N; ++k) { + printf("%3d", t1.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < K-1) printf("],\n ["); + else printf("])\n"); + } + } + printf("t0 = (["); + for(j = 0; j < K; ++j) { + for(k = 0; k < N; ++k) { + printf("%5d", t0.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < K-1) printf("],\n ["); + else printf("])\n"); + } + } + + poly_challenge(&c, seed); + printf("c = ["); + for(j = 0; j < N; ++j) { + printf("%2d", c.coeffs[j]); + if(j < N-1) printf(", "); + else printf("]\n"); + } + + printf("\n"); + } + + return 0; +} diff --git a/ref/.gitignore b/ref/.gitignore new file mode 100644 index 0000000..cc78368 --- /dev/null +++ b/ref/.gitignore @@ -0,0 +1,2 @@ +*.so +*.o diff --git a/ref/Makefile b/ref/Makefile new file mode 100644 index 0000000..2c94d35 --- /dev/null +++ b/ref/Makefile @@ -0,0 +1,139 @@ +CC ?= /usr/bin/cc +CFLAGS += -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wredundant-decls \ + -Wshadow -Wvla -Wpointer-arith -O3 -fomit-frame-pointer +NISTFLAGS += -Wno-unused-result -O3 -fomit-frame-pointer +SOURCES = sign.c packing.c polyvec.c poly.c ntt.c reduce.c rounding.c +HEADERS = config.h params.h api.h sign.h packing.h polyvec.h poly.h ntt.h \ + reduce.h rounding.h symmetric.h randombytes.h +KECCAK_SOURCES = $(SOURCES) fips202.c symmetric-shake.c +KECCAK_HEADERS = $(HEADERS) fips202.h + +.PHONY: all speed shared clean + +all: \ + test/test_dilithium2 \ + test/test_dilithium3 \ + test/test_dilithium5 \ + test/test_vectors2 \ + test/test_vectors3 \ + test/test_vectors5 + +nistkat: \ + nistkat/PQCgenKAT_sign2 \ + nistkat/PQCgenKAT_sign3 \ + nistkat/PQCgenKAT_sign5 + +speed: \ + test/test_mul \ + test/test_speed2 \ + test/test_speed3 \ + test/test_speed5 \ + +shared: \ + libpqcrystals_dilithium2_ref.so \ + libpqcrystals_dilithium3_ref.so \ + libpqcrystals_dilithium5_ref.so \ + libpqcrystals_fips202_ref.so \ + +libpqcrystals_fips202_ref.so: fips202.c fips202.h + $(CC) -shared -fPIC $(CFLAGS) -o $@ $< + +libpqcrystals_dilithium2_ref.so: $(SOURCES) $(HEADERS) symmetric-shake.c + $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=2 \ + -o $@ $(SOURCES) symmetric-shake.c + +libpqcrystals_dilithium3_ref.so: $(SOURCES) $(HEADERS) symmetric-shake.c + $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=3 \ + -o $@ $(SOURCES) symmetric-shake.c + +libpqcrystals_dilithium5_ref.so: $(SOURCES) $(HEADERS) symmetric-shake.c + $(CC) -shared -fPIC $(CFLAGS) -DDILITHIUM_MODE=5 \ + -o $@ $(SOURCES) symmetric-shake.c + +test/test_dilithium2: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ + -o $@ $< randombytes.c $(KECCAK_SOURCES) + +test/test_dilithium3: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ + -o $@ $< randombytes.c $(KECCAK_SOURCES) + +test/test_dilithium5: test/test_dilithium.c randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ + -o $@ $< randombytes.c $(KECCAK_SOURCES) + +test/test_vectors2: test/test_vectors.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ + -o $@ $< $(KECCAK_SOURCES) + +test/test_vectors3: test/test_vectors.c $(KECCAK_SOURCES) $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ + -o $@ $< $(KECCAK_SOURCES) + +test/test_vectors5: test/test_vectors.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ + -o $@ $< $(KECCAK_SOURCES) + +test/test_speed2: test/test_speed.c test/speed_print.c test/speed_print.h \ + test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=2 \ + -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ + $(KECCAK_SOURCES) + +test/test_speed3: test/test_speed.c test/speed_print.c test/speed_print.h \ + test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=3 \ + -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ + $(KECCAK_SOURCES) + +test/test_speed5: test/test_speed.c test/speed_print.c test/speed_print.h \ + test/cpucycles.c test/cpucycles.h randombytes.c $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -DDILITHIUM_MODE=5 \ + -o $@ $< test/speed_print.c test/cpucycles.c randombytes.c \ + $(KECCAK_SOURCES) + +test/test_mul: test/test_mul.c randombytes.c $(KECCAK_SOURCES) $(KECCAK_HEADERS) + $(CC) $(CFLAGS) -UDBENCH -o $@ $< randombytes.c $(KECCAK_SOURCES) + +nistkat/PQCgenKAT_sign2: nistkat/PQCgenKAT_sign.c nistkat/rng.c nistkat/rng.h $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(NISTFLAGS) -DDILITHIUM_MODE=2 \ + -o $@ $< nistkat/rng.c $(KECCAK_SOURCES) $(LDFLAGS) -lcrypto + +nistkat/PQCgenKAT_sign3: nistkat/PQCgenKAT_sign.c nistkat/rng.c nistkat/rng.h $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(NISTFLAGS) -DDILITHIUM_MODE=3 \ + -o $@ $< nistkat/rng.c $(KECCAK_SOURCES) $(LDFLAGS) -lcrypto + +nistkat/PQCgenKAT_sign5: nistkat/PQCgenKAT_sign.c nistkat/rng.c nistkat/rng.h $(KECCAK_SOURCES) \ + $(KECCAK_HEADERS) + $(CC) $(NISTFLAGS) -DDILITHIUM_MODE=5 \ + -o $@ $< nistkat/rng.c $(KECCAK_SOURCES) $(LDFLAGS) -lcrypto + +clean: + rm -f *~ test/*~ *.gcno *.gcda *.lcov + rm -f libpqcrystals_dilithium2_ref.so + rm -f libpqcrystals_dilithium3_ref.so + rm -f libpqcrystals_dilithium5_ref.so + rm -f libpqcrystals_fips202_ref.so + rm -f test/test_dilithium2 + rm -f test/test_dilithium3 + rm -f test/test_dilithium5 + rm -f test/test_vectors2 + rm -f test/test_vectors3 + rm -f test/test_vectors5 + rm -f test/test_speed2 + rm -f test/test_speed3 + rm -f test/test_speed5 + rm -f test/test_mul + rm -f nistkat/PQCgenKAT_sign2 + rm -f nistkat/PQCgenKAT_sign3 + rm -f nistkat/PQCgenKAT_sign5 diff --git a/ref/api.h b/ref/api.h new file mode 100644 index 0000000..032fa9f --- /dev/null +++ b/ref/api.h @@ -0,0 +1,98 @@ +#ifndef API_H +#define API_H + +#include +#include + +#define pqcrystals_dilithium2_PUBLICKEYBYTES 1312 +#define pqcrystals_dilithium2_SECRETKEYBYTES 2560 +#define pqcrystals_dilithium2_BYTES 2420 + +#define pqcrystals_dilithium2_ref_PUBLICKEYBYTES pqcrystals_dilithium2_PUBLICKEYBYTES +#define pqcrystals_dilithium2_ref_SECRETKEYBYTES pqcrystals_dilithium2_SECRETKEYBYTES +#define pqcrystals_dilithium2_ref_BYTES pqcrystals_dilithium2_BYTES + +int pqcrystals_dilithium2_ref_keypair(uint8_t *pk, uint8_t *sk); + +int pqcrystals_dilithium2_ref_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium2_ref(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium2_ref_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +int pqcrystals_dilithium2_ref_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +#define pqcrystals_dilithium3_PUBLICKEYBYTES 1952 +#define pqcrystals_dilithium3_SECRETKEYBYTES 4032 +#define pqcrystals_dilithium3_BYTES 3309 + +#define pqcrystals_dilithium3_ref_PUBLICKEYBYTES pqcrystals_dilithium3_PUBLICKEYBYTES +#define pqcrystals_dilithium3_ref_SECRETKEYBYTES pqcrystals_dilithium3_SECRETKEYBYTES +#define pqcrystals_dilithium3_ref_BYTES pqcrystals_dilithium3_BYTES + +int pqcrystals_dilithium3_ref_keypair(uint8_t *pk, uint8_t *sk); + +int pqcrystals_dilithium3_ref_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium3_ref(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium3_ref_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +int pqcrystals_dilithium3_ref_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +#define pqcrystals_dilithium5_PUBLICKEYBYTES 2592 +#define pqcrystals_dilithium5_SECRETKEYBYTES 4896 +#define pqcrystals_dilithium5_BYTES 4627 + +#define pqcrystals_dilithium5_ref_PUBLICKEYBYTES pqcrystals_dilithium5_PUBLICKEYBYTES +#define pqcrystals_dilithium5_ref_SECRETKEYBYTES pqcrystals_dilithium5_SECRETKEYBYTES +#define pqcrystals_dilithium5_ref_BYTES pqcrystals_dilithium5_BYTES + +int pqcrystals_dilithium5_ref_keypair(uint8_t *pk, uint8_t *sk); + +int pqcrystals_dilithium5_ref_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium5_ref(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int pqcrystals_dilithium5_ref_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +int pqcrystals_dilithium5_ref_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + + +#endif diff --git a/ref/config.h b/ref/config.h new file mode 100644 index 0000000..98b8ccb --- /dev/null +++ b/ref/config.h @@ -0,0 +1,27 @@ +#ifndef CONFIG_H +#define CONFIG_H + +//#define DILITHIUM_MODE 2 +#define DILITHIUM_RANDOMIZED_SIGNING +//#define USE_RDPMC +//#define DBENCH + +#ifndef DILITHIUM_MODE +#define DILITHIUM_MODE 2 +#endif + +#if DILITHIUM_MODE == 2 +#define CRYPTO_ALGNAME "Dilithium2" +#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium2_ref +#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium2_ref_##s +#elif DILITHIUM_MODE == 3 +#define CRYPTO_ALGNAME "Dilithium3" +#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium3_ref +#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium3_ref_##s +#elif DILITHIUM_MODE == 5 +#define CRYPTO_ALGNAME "Dilithium5" +#define DILITHIUM_NAMESPACETOP pqcrystals_dilithium5_ref +#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium5_ref_##s +#endif + +#endif diff --git a/ref/fips202.c b/ref/fips202.c new file mode 100644 index 0000000..2afe799 --- /dev/null +++ b/ref/fips202.c @@ -0,0 +1,774 @@ +/* Based on the public domain implementation in crypto_hash/keccakc512/simple/ from + * http://bench.cr.yp.to/supercop.html by Ronny Van Keer and the public domain "TweetFips202" + * implementation from https://twitter.com/tweetfips202 by Gilles Van Assche, Daniel J. Bernstein, + * and Peter Schwabe */ + +#include +#include +#include "fips202.h" + +#define NROUNDS 24 +#define ROL(a, offset) ((a << offset) ^ (a >> (64-offset))) + +/************************************************* +* Name: load64 +* +* Description: Load 8 bytes into uint64_t in little-endian order +* +* Arguments: - const uint8_t *x: pointer to input byte array +* +* Returns the loaded 64-bit unsigned integer +**************************************************/ +static uint64_t load64(const uint8_t x[8]) { + unsigned int i; + uint64_t r = 0; + + for(i=0;i<8;i++) + r |= (uint64_t)x[i] << 8*i; + + return r; +} + +/************************************************* +* Name: store64 +* +* Description: Store a 64-bit integer to array of 8 bytes in little-endian order +* +* Arguments: - uint8_t *x: pointer to the output byte array (allocated) +* - uint64_t u: input 64-bit unsigned integer +**************************************************/ +static void store64(uint8_t x[8], uint64_t u) { + unsigned int i; + + for(i=0;i<8;i++) + x[i] = u >> 8*i; +} + +/* Keccak round constants */ +const uint64_t KeccakF_RoundConstants[NROUNDS] = { + (uint64_t)0x0000000000000001ULL, + (uint64_t)0x0000000000008082ULL, + (uint64_t)0x800000000000808aULL, + (uint64_t)0x8000000080008000ULL, + (uint64_t)0x000000000000808bULL, + (uint64_t)0x0000000080000001ULL, + (uint64_t)0x8000000080008081ULL, + (uint64_t)0x8000000000008009ULL, + (uint64_t)0x000000000000008aULL, + (uint64_t)0x0000000000000088ULL, + (uint64_t)0x0000000080008009ULL, + (uint64_t)0x000000008000000aULL, + (uint64_t)0x000000008000808bULL, + (uint64_t)0x800000000000008bULL, + (uint64_t)0x8000000000008089ULL, + (uint64_t)0x8000000000008003ULL, + (uint64_t)0x8000000000008002ULL, + (uint64_t)0x8000000000000080ULL, + (uint64_t)0x000000000000800aULL, + (uint64_t)0x800000008000000aULL, + (uint64_t)0x8000000080008081ULL, + (uint64_t)0x8000000000008080ULL, + (uint64_t)0x0000000080000001ULL, + (uint64_t)0x8000000080008008ULL +}; + +/************************************************* +* Name: KeccakF1600_StatePermute +* +* Description: The Keccak F1600 Permutation +* +* Arguments: - uint64_t *state: pointer to input/output Keccak state +**************************************************/ +static void KeccakF1600_StatePermute(uint64_t state[25]) +{ + int round; + + uint64_t Aba, Abe, Abi, Abo, Abu; + uint64_t Aga, Age, Agi, Ago, Agu; + uint64_t Aka, Ake, Aki, Ako, Aku; + uint64_t Ama, Ame, Ami, Amo, Amu; + uint64_t Asa, Ase, Asi, Aso, Asu; + uint64_t BCa, BCe, BCi, BCo, BCu; + uint64_t Da, De, Di, Do, Du; + uint64_t Eba, Ebe, Ebi, Ebo, Ebu; + uint64_t Ega, Ege, Egi, Ego, Egu; + uint64_t Eka, Eke, Eki, Eko, Eku; + uint64_t Ema, Eme, Emi, Emo, Emu; + uint64_t Esa, Ese, Esi, Eso, Esu; + + //copyFromState(A, state) + Aba = state[ 0]; + Abe = state[ 1]; + Abi = state[ 2]; + Abo = state[ 3]; + Abu = state[ 4]; + Aga = state[ 5]; + Age = state[ 6]; + Agi = state[ 7]; + Ago = state[ 8]; + Agu = state[ 9]; + Aka = state[10]; + Ake = state[11]; + Aki = state[12]; + Ako = state[13]; + Aku = state[14]; + Ama = state[15]; + Ame = state[16]; + Ami = state[17]; + Amo = state[18]; + Amu = state[19]; + Asa = state[20]; + Ase = state[21]; + Asi = state[22]; + Aso = state[23]; + Asu = state[24]; + + for(round = 0; round < NROUNDS; round += 2) { + // prepareTheta + BCa = Aba^Aga^Aka^Ama^Asa; + BCe = Abe^Age^Ake^Ame^Ase; + BCi = Abi^Agi^Aki^Ami^Asi; + BCo = Abo^Ago^Ako^Amo^Aso; + BCu = Abu^Agu^Aku^Amu^Asu; + + //thetaRhoPiChiIotaPrepareTheta(round, A, E) + Da = BCu^ROL(BCe, 1); + De = BCa^ROL(BCi, 1); + Di = BCe^ROL(BCo, 1); + Do = BCi^ROL(BCu, 1); + Du = BCo^ROL(BCa, 1); + + Aba ^= Da; + BCa = Aba; + Age ^= De; + BCe = ROL(Age, 44); + Aki ^= Di; + BCi = ROL(Aki, 43); + Amo ^= Do; + BCo = ROL(Amo, 21); + Asu ^= Du; + BCu = ROL(Asu, 14); + Eba = BCa ^((~BCe)& BCi ); + Eba ^= (uint64_t)KeccakF_RoundConstants[round]; + Ebe = BCe ^((~BCi)& BCo ); + Ebi = BCi ^((~BCo)& BCu ); + Ebo = BCo ^((~BCu)& BCa ); + Ebu = BCu ^((~BCa)& BCe ); + + Abo ^= Do; + BCa = ROL(Abo, 28); + Agu ^= Du; + BCe = ROL(Agu, 20); + Aka ^= Da; + BCi = ROL(Aka, 3); + Ame ^= De; + BCo = ROL(Ame, 45); + Asi ^= Di; + BCu = ROL(Asi, 61); + Ega = BCa ^((~BCe)& BCi ); + Ege = BCe ^((~BCi)& BCo ); + Egi = BCi ^((~BCo)& BCu ); + Ego = BCo ^((~BCu)& BCa ); + Egu = BCu ^((~BCa)& BCe ); + + Abe ^= De; + BCa = ROL(Abe, 1); + Agi ^= Di; + BCe = ROL(Agi, 6); + Ako ^= Do; + BCi = ROL(Ako, 25); + Amu ^= Du; + BCo = ROL(Amu, 8); + Asa ^= Da; + BCu = ROL(Asa, 18); + Eka = BCa ^((~BCe)& BCi ); + Eke = BCe ^((~BCi)& BCo ); + Eki = BCi ^((~BCo)& BCu ); + Eko = BCo ^((~BCu)& BCa ); + Eku = BCu ^((~BCa)& BCe ); + + Abu ^= Du; + BCa = ROL(Abu, 27); + Aga ^= Da; + BCe = ROL(Aga, 36); + Ake ^= De; + BCi = ROL(Ake, 10); + Ami ^= Di; + BCo = ROL(Ami, 15); + Aso ^= Do; + BCu = ROL(Aso, 56); + Ema = BCa ^((~BCe)& BCi ); + Eme = BCe ^((~BCi)& BCo ); + Emi = BCi ^((~BCo)& BCu ); + Emo = BCo ^((~BCu)& BCa ); + Emu = BCu ^((~BCa)& BCe ); + + Abi ^= Di; + BCa = ROL(Abi, 62); + Ago ^= Do; + BCe = ROL(Ago, 55); + Aku ^= Du; + BCi = ROL(Aku, 39); + Ama ^= Da; + BCo = ROL(Ama, 41); + Ase ^= De; + BCu = ROL(Ase, 2); + Esa = BCa ^((~BCe)& BCi ); + Ese = BCe ^((~BCi)& BCo ); + Esi = BCi ^((~BCo)& BCu ); + Eso = BCo ^((~BCu)& BCa ); + Esu = BCu ^((~BCa)& BCe ); + + // prepareTheta + BCa = Eba^Ega^Eka^Ema^Esa; + BCe = Ebe^Ege^Eke^Eme^Ese; + BCi = Ebi^Egi^Eki^Emi^Esi; + BCo = Ebo^Ego^Eko^Emo^Eso; + BCu = Ebu^Egu^Eku^Emu^Esu; + + //thetaRhoPiChiIotaPrepareTheta(round+1, E, A) + Da = BCu^ROL(BCe, 1); + De = BCa^ROL(BCi, 1); + Di = BCe^ROL(BCo, 1); + Do = BCi^ROL(BCu, 1); + Du = BCo^ROL(BCa, 1); + + Eba ^= Da; + BCa = Eba; + Ege ^= De; + BCe = ROL(Ege, 44); + Eki ^= Di; + BCi = ROL(Eki, 43); + Emo ^= Do; + BCo = ROL(Emo, 21); + Esu ^= Du; + BCu = ROL(Esu, 14); + Aba = BCa ^((~BCe)& BCi ); + Aba ^= (uint64_t)KeccakF_RoundConstants[round+1]; + Abe = BCe ^((~BCi)& BCo ); + Abi = BCi ^((~BCo)& BCu ); + Abo = BCo ^((~BCu)& BCa ); + Abu = BCu ^((~BCa)& BCe ); + + Ebo ^= Do; + BCa = ROL(Ebo, 28); + Egu ^= Du; + BCe = ROL(Egu, 20); + Eka ^= Da; + BCi = ROL(Eka, 3); + Eme ^= De; + BCo = ROL(Eme, 45); + Esi ^= Di; + BCu = ROL(Esi, 61); + Aga = BCa ^((~BCe)& BCi ); + Age = BCe ^((~BCi)& BCo ); + Agi = BCi ^((~BCo)& BCu ); + Ago = BCo ^((~BCu)& BCa ); + Agu = BCu ^((~BCa)& BCe ); + + Ebe ^= De; + BCa = ROL(Ebe, 1); + Egi ^= Di; + BCe = ROL(Egi, 6); + Eko ^= Do; + BCi = ROL(Eko, 25); + Emu ^= Du; + BCo = ROL(Emu, 8); + Esa ^= Da; + BCu = ROL(Esa, 18); + Aka = BCa ^((~BCe)& BCi ); + Ake = BCe ^((~BCi)& BCo ); + Aki = BCi ^((~BCo)& BCu ); + Ako = BCo ^((~BCu)& BCa ); + Aku = BCu ^((~BCa)& BCe ); + + Ebu ^= Du; + BCa = ROL(Ebu, 27); + Ega ^= Da; + BCe = ROL(Ega, 36); + Eke ^= De; + BCi = ROL(Eke, 10); + Emi ^= Di; + BCo = ROL(Emi, 15); + Eso ^= Do; + BCu = ROL(Eso, 56); + Ama = BCa ^((~BCe)& BCi ); + Ame = BCe ^((~BCi)& BCo ); + Ami = BCi ^((~BCo)& BCu ); + Amo = BCo ^((~BCu)& BCa ); + Amu = BCu ^((~BCa)& BCe ); + + Ebi ^= Di; + BCa = ROL(Ebi, 62); + Ego ^= Do; + BCe = ROL(Ego, 55); + Eku ^= Du; + BCi = ROL(Eku, 39); + Ema ^= Da; + BCo = ROL(Ema, 41); + Ese ^= De; + BCu = ROL(Ese, 2); + Asa = BCa ^((~BCe)& BCi ); + Ase = BCe ^((~BCi)& BCo ); + Asi = BCi ^((~BCo)& BCu ); + Aso = BCo ^((~BCu)& BCa ); + Asu = BCu ^((~BCa)& BCe ); + } + + //copyToState(state, A) + state[ 0] = Aba; + state[ 1] = Abe; + state[ 2] = Abi; + state[ 3] = Abo; + state[ 4] = Abu; + state[ 5] = Aga; + state[ 6] = Age; + state[ 7] = Agi; + state[ 8] = Ago; + state[ 9] = Agu; + state[10] = Aka; + state[11] = Ake; + state[12] = Aki; + state[13] = Ako; + state[14] = Aku; + state[15] = Ama; + state[16] = Ame; + state[17] = Ami; + state[18] = Amo; + state[19] = Amu; + state[20] = Asa; + state[21] = Ase; + state[22] = Asi; + state[23] = Aso; + state[24] = Asu; +} + +/************************************************* +* Name: keccak_init +* +* Description: Initializes the Keccak state. +* +* Arguments: - uint64_t *s: pointer to Keccak state +**************************************************/ +static void keccak_init(uint64_t s[25]) +{ + unsigned int i; + for(i=0;i<25;i++) + s[i] = 0; +} + +/************************************************* +* Name: keccak_absorb +* +* Description: Absorb step of Keccak; incremental. +* +* Arguments: - uint64_t *s: pointer to Keccak state +* - unsigned int pos: position in current block to be absorbed +* - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) +* - const uint8_t *in: pointer to input to be absorbed into s +* - size_t inlen: length of input in bytes +* +* Returns new position pos in current block +**************************************************/ +static unsigned int keccak_absorb(uint64_t s[25], + unsigned int pos, + unsigned int r, + const uint8_t *in, + size_t inlen) +{ + unsigned int i; + + while(pos+inlen >= r) { + for(i=pos;i> 8*(i%8); + outlen -= i-pos; + pos = i; + } + + return pos; +} + + +/************************************************* +* Name: keccak_absorb_once +* +* Description: Absorb step of Keccak; +* non-incremental, starts by zeroeing the state. +* +* Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state +* - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) +* - const uint8_t *in: pointer to input to be absorbed into s +* - size_t inlen: length of input in bytes +* - uint8_t p: domain-separation byte for different Keccak-derived functions +**************************************************/ +static void keccak_absorb_once(uint64_t s[25], + unsigned int r, + const uint8_t *in, + size_t inlen, + uint8_t p) +{ + unsigned int i; + + for(i=0;i<25;i++) + s[i] = 0; + + while(inlen >= r) { + for(i=0;is); + state->pos = 0; +} + +/************************************************* +* Name: shake128_absorb +* +* Description: Absorb step of the SHAKE128 XOF; incremental. +* +* Arguments: - keccak_state *state: pointer to (initialized) output Keccak state +* - const uint8_t *in: pointer to input to be absorbed into s +* - size_t inlen: length of input in bytes +**************************************************/ +void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen) +{ + state->pos = keccak_absorb(state->s, state->pos, SHAKE128_RATE, in, inlen); +} + +/************************************************* +* Name: shake128_finalize +* +* Description: Finalize absorb step of the SHAKE128 XOF. +* +* Arguments: - keccak_state *state: pointer to Keccak state +**************************************************/ +void shake128_finalize(keccak_state *state) +{ + keccak_finalize(state->s, state->pos, SHAKE128_RATE, 0x1F); + state->pos = SHAKE128_RATE; +} + +/************************************************* +* Name: shake128_squeeze +* +* Description: Squeeze step of SHAKE128 XOF. Squeezes arbitraily many +* bytes. Can be called multiple times to keep squeezing. +* +* Arguments: - uint8_t *out: pointer to output blocks +* - size_t outlen : number of bytes to be squeezed (written to output) +* - keccak_state *s: pointer to input/output Keccak state +**************************************************/ +void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state) +{ + state->pos = keccak_squeeze(out, outlen, state->s, state->pos, SHAKE128_RATE); +} + +/************************************************* +* Name: shake128_absorb_once +* +* Description: Initialize, absorb into and finalize SHAKE128 XOF; non-incremental. +* +* Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak state +* - const uint8_t *in: pointer to input to be absorbed into s +* - size_t inlen: length of input in bytes +**************************************************/ +void shake128_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen) +{ + keccak_absorb_once(state->s, SHAKE128_RATE, in, inlen, 0x1F); + state->pos = SHAKE128_RATE; +} + +/************************************************* +* Name: shake128_squeezeblocks +* +* Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of +* SHAKE128_RATE bytes each. Can be called multiple times +* to keep squeezing. Assumes new block has not yet been +* started (state->pos = SHAKE128_RATE). +* +* Arguments: - uint8_t *out: pointer to output blocks +* - size_t nblocks: number of blocks to be squeezed (written to output) +* - keccak_state *s: pointer to input/output Keccak state +**************************************************/ +void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) +{ + keccak_squeezeblocks(out, nblocks, state->s, SHAKE128_RATE); +} + +/************************************************* +* Name: shake256_init +* +* Description: Initilizes Keccak state for use as SHAKE256 XOF +* +* Arguments: - keccak_state *state: pointer to (uninitialized) Keccak state +**************************************************/ +void shake256_init(keccak_state *state) +{ + keccak_init(state->s); + state->pos = 0; +} + +/************************************************* +* Name: shake256_absorb +* +* Description: Absorb step of the SHAKE256 XOF; incremental. +* +* Arguments: - keccak_state *state: pointer to (initialized) output Keccak state +* - const uint8_t *in: pointer to input to be absorbed into s +* - size_t inlen: length of input in bytes +**************************************************/ +void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen) +{ + state->pos = keccak_absorb(state->s, state->pos, SHAKE256_RATE, in, inlen); +} + +/************************************************* +* Name: shake256_finalize +* +* Description: Finalize absorb step of the SHAKE256 XOF. +* +* Arguments: - keccak_state *state: pointer to Keccak state +**************************************************/ +void shake256_finalize(keccak_state *state) +{ + keccak_finalize(state->s, state->pos, SHAKE256_RATE, 0x1F); + state->pos = SHAKE256_RATE; +} + +/************************************************* +* Name: shake256_squeeze +* +* Description: Squeeze step of SHAKE256 XOF. Squeezes arbitraily many +* bytes. Can be called multiple times to keep squeezing. +* +* Arguments: - uint8_t *out: pointer to output blocks +* - size_t outlen : number of bytes to be squeezed (written to output) +* - keccak_state *s: pointer to input/output Keccak state +**************************************************/ +void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state) +{ + state->pos = keccak_squeeze(out, outlen, state->s, state->pos, SHAKE256_RATE); +} + +/************************************************* +* Name: shake256_absorb_once +* +* Description: Initialize, absorb into and finalize SHAKE256 XOF; non-incremental. +* +* Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak state +* - const uint8_t *in: pointer to input to be absorbed into s +* - size_t inlen: length of input in bytes +**************************************************/ +void shake256_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen) +{ + keccak_absorb_once(state->s, SHAKE256_RATE, in, inlen, 0x1F); + state->pos = SHAKE256_RATE; +} + +/************************************************* +* Name: shake256_squeezeblocks +* +* Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of +* SHAKE256_RATE bytes each. Can be called multiple times +* to keep squeezing. Assumes next block has not yet been +* started (state->pos = SHAKE256_RATE). +* +* Arguments: - uint8_t *out: pointer to output blocks +* - size_t nblocks: number of blocks to be squeezed (written to output) +* - keccak_state *s: pointer to input/output Keccak state +**************************************************/ +void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) +{ + keccak_squeezeblocks(out, nblocks, state->s, SHAKE256_RATE); +} + +/************************************************* +* Name: shake128 +* +* Description: SHAKE128 XOF with non-incremental API +* +* Arguments: - uint8_t *out: pointer to output +* - size_t outlen: requested output length in bytes +* - const uint8_t *in: pointer to input +* - size_t inlen: length of input in bytes +**************************************************/ +void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) +{ + size_t nblocks; + keccak_state state; + + shake128_absorb_once(&state, in, inlen); + nblocks = outlen/SHAKE128_RATE; + shake128_squeezeblocks(out, nblocks, &state); + outlen -= nblocks*SHAKE128_RATE; + out += nblocks*SHAKE128_RATE; + shake128_squeeze(out, outlen, &state); +} + +/************************************************* +* Name: shake256 +* +* Description: SHAKE256 XOF with non-incremental API +* +* Arguments: - uint8_t *out: pointer to output +* - size_t outlen: requested output length in bytes +* - const uint8_t *in: pointer to input +* - size_t inlen: length of input in bytes +**************************************************/ +void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) +{ + size_t nblocks; + keccak_state state; + + shake256_absorb_once(&state, in, inlen); + nblocks = outlen/SHAKE256_RATE; + shake256_squeezeblocks(out, nblocks, &state); + outlen -= nblocks*SHAKE256_RATE; + out += nblocks*SHAKE256_RATE; + shake256_squeeze(out, outlen, &state); +} + +/************************************************* +* Name: sha3_256 +* +* Description: SHA3-256 with non-incremental API +* +* Arguments: - uint8_t *h: pointer to output (32 bytes) +* - const uint8_t *in: pointer to input +* - size_t inlen: length of input in bytes +**************************************************/ +void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen) +{ + unsigned int i; + uint64_t s[25]; + + keccak_absorb_once(s, SHA3_256_RATE, in, inlen, 0x06); + KeccakF1600_StatePermute(s); + for(i=0;i<4;i++) + store64(h+8*i,s[i]); +} + +/************************************************* +* Name: sha3_512 +* +* Description: SHA3-512 with non-incremental API +* +* Arguments: - uint8_t *h: pointer to output (64 bytes) +* - const uint8_t *in: pointer to input +* - size_t inlen: length of input in bytes +**************************************************/ +void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen) +{ + unsigned int i; + uint64_t s[25]; + + keccak_absorb_once(s, SHA3_512_RATE, in, inlen, 0x06); + KeccakF1600_StatePermute(s); + for(i=0;i<8;i++) + store64(h+8*i,s[i]); +} diff --git a/ref/fips202.h b/ref/fips202.h new file mode 100644 index 0000000..c37f535 --- /dev/null +++ b/ref/fips202.h @@ -0,0 +1,57 @@ +#ifndef FIPS202_H +#define FIPS202_H + +#include +#include + +#define SHAKE128_RATE 168 +#define SHAKE256_RATE 136 +#define SHA3_256_RATE 136 +#define SHA3_512_RATE 72 + +#define FIPS202_NAMESPACE(s) pqcrystals_dilithium_fips202_ref_##s + +typedef struct { + uint64_t s[25]; + unsigned int pos; +} keccak_state; + +#define KeccakF_RoundConstants FIPS202_NAMESPACE(KeccakF_RoundConstants) +extern const uint64_t KeccakF_RoundConstants[]; + +#define shake128_init FIPS202_NAMESPACE(shake128_init) +void shake128_init(keccak_state *state); +#define shake128_absorb FIPS202_NAMESPACE(shake128_absorb) +void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake128_finalize FIPS202_NAMESPACE(shake128_finalize) +void shake128_finalize(keccak_state *state); +#define shake128_squeeze FIPS202_NAMESPACE(shake128_squeeze) +void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state); +#define shake128_absorb_once FIPS202_NAMESPACE(shake128_absorb_once) +void shake128_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake128_squeezeblocks FIPS202_NAMESPACE(shake128_squeezeblocks) +void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); + +#define shake256_init FIPS202_NAMESPACE(shake256_init) +void shake256_init(keccak_state *state); +#define shake256_absorb FIPS202_NAMESPACE(shake256_absorb) +void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake256_finalize FIPS202_NAMESPACE(shake256_finalize) +void shake256_finalize(keccak_state *state); +#define shake256_squeeze FIPS202_NAMESPACE(shake256_squeeze) +void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state); +#define shake256_absorb_once FIPS202_NAMESPACE(shake256_absorb_once) +void shake256_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake256_squeezeblocks FIPS202_NAMESPACE(shake256_squeezeblocks) +void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); + +#define shake128 FIPS202_NAMESPACE(shake128) +void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); +#define shake256 FIPS202_NAMESPACE(shake256) +void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); +#define sha3_256 FIPS202_NAMESPACE(sha3_256) +void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen); +#define sha3_512 FIPS202_NAMESPACE(sha3_512) +void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen); + +#endif diff --git a/ref/nistkat/.gitignore b/ref/nistkat/.gitignore new file mode 100644 index 0000000..0aa8057 --- /dev/null +++ b/ref/nistkat/.gitignore @@ -0,0 +1,3 @@ +PQCgenKAT_sign2 +PQCgenKAT_sign3 +PQCgenKAT_sign5 diff --git a/ref/nistkat/PQCgenKAT_sign.c b/ref/nistkat/PQCgenKAT_sign.c new file mode 100644 index 0000000..005ce41 --- /dev/null +++ b/ref/nistkat/PQCgenKAT_sign.c @@ -0,0 +1,261 @@ +// +// PQCgenKAT_sign.c +// +// Created by Bassham, Lawrence E (Fed) on 8/29/17. +// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. +// +#include +#include +#include +#include +#include +#include "rng.h" +#include "../sign.h" + +#define MAX_MARKER_LEN 50 + +#define KAT_SUCCESS 0 +#define KAT_FILE_OPEN_ERROR -1 +#define KAT_DATA_ERROR -3 +#define KAT_CRYPTO_FAILURE -4 + +int FindMarker(FILE *infile, const char *marker); +int ReadHex(FILE *infile, unsigned char *a, int Length, char *str); +void fprintBstr(FILE *fp, char *s, unsigned char *a, unsigned long long l); + +int +main() +{ + char fn_req[32], fn_rsp[32]; + FILE *fp_req, *fp_rsp; + uint8_t seed[48]; + uint8_t msg[3300]; + uint8_t entropy_input[48]; + uint8_t *m, *sm, *m1; + size_t mlen, smlen, mlen1; + int count; + int done; + uint8_t pk[CRYPTO_PUBLICKEYBYTES], sk[CRYPTO_SECRETKEYBYTES]; + int ret_val; + + // Create the REQUEST file + sprintf(fn_req, "PQCsignKAT_%.16s.req", CRYPTO_ALGNAME); + if ( (fp_req = fopen(fn_req, "w")) == NULL ) { + printf("Couldn't open <%s> for write\n", fn_req); + return KAT_FILE_OPEN_ERROR; + } + sprintf(fn_rsp, "PQCsignKAT_%.16s.rsp", CRYPTO_ALGNAME); + if ( (fp_rsp = fopen(fn_rsp, "w")) == NULL ) { + printf("Couldn't open <%s> for write\n", fn_rsp); + return KAT_FILE_OPEN_ERROR; + } + + for (int i=0; i<48; i++) + entropy_input[i] = i; + + randombytes_init(entropy_input, NULL, 256); + for (int i=0; i<100; i++) { + fprintf(fp_req, "count = %d\n", i); + randombytes(seed, 48); + fprintBstr(fp_req, "seed = ", seed, 48); + mlen = 33*(i+1); + fprintf(fp_req, "mlen = %lu\n", mlen); + randombytes(msg, mlen); + fprintBstr(fp_req, "msg = ", msg, mlen); + fprintf(fp_req, "pk =\n"); + fprintf(fp_req, "sk =\n"); + fprintf(fp_req, "smlen =\n"); + fprintf(fp_req, "sm =\n\n"); + } + fclose(fp_req); + + //Create the RESPONSE file based on what's in the REQUEST file + if ( (fp_req = fopen(fn_req, "r")) == NULL ) { + printf("Couldn't open <%s> for read\n", fn_req); + return KAT_FILE_OPEN_ERROR; + } + + fprintf(fp_rsp, "# %s\n\n", CRYPTO_ALGNAME); + done = 0; + do { + if ( FindMarker(fp_req, "count = ") ) + fscanf(fp_req, "%d", &count); + else { + done = 1; + break; + } + fprintf(fp_rsp, "count = %d\n", count); + + if ( !ReadHex(fp_req, seed, 48, "seed = ") ) { + printf("ERROR: unable to read 'seed' from <%s>\n", fn_req); + return KAT_DATA_ERROR; + } + fprintBstr(fp_rsp, "seed = ", seed, 48); + + randombytes_init(seed, NULL, 256); + + if ( FindMarker(fp_req, "mlen = ") ) + fscanf(fp_req, "%lu", &mlen); + else { + printf("ERROR: unable to read 'mlen' from <%s>\n", fn_req); + return KAT_DATA_ERROR; + } + fprintf(fp_rsp, "mlen = %lu\n", mlen); + + m = (uint8_t *)calloc(mlen, sizeof(uint8_t)); + m1 = (uint8_t *)calloc(mlen+CRYPTO_BYTES, sizeof(uint8_t)); + sm = (uint8_t *)calloc(mlen+CRYPTO_BYTES, sizeof(uint8_t)); + + if ( !ReadHex(fp_req, m, (int)mlen, "msg = ") ) { + printf("ERROR: unable to read 'msg' from <%s>\n", fn_req); + return KAT_DATA_ERROR; + } + fprintBstr(fp_rsp, "msg = ", m, mlen); + + // Generate the public/private keypair + if ( (ret_val = crypto_sign_keypair(pk, sk)) != 0) { + printf("crypto_sign_keypair returned <%d>\n", ret_val); + return KAT_CRYPTO_FAILURE; + } + fprintBstr(fp_rsp, "pk = ", pk, CRYPTO_PUBLICKEYBYTES); + fprintBstr(fp_rsp, "sk = ", sk, CRYPTO_SECRETKEYBYTES); + + if ( (ret_val = crypto_sign(sm, &smlen, m, mlen, NULL, 0, sk)) != 0) { + printf("crypto_sign returned <%d>\n", ret_val); + return KAT_CRYPTO_FAILURE; + } + fprintf(fp_rsp, "smlen = %lu\n", smlen); + fprintBstr(fp_rsp, "sm = ", sm, smlen); + fprintf(fp_rsp, "\n"); + + if ( (ret_val = crypto_sign_open(m1, &mlen1, sm, smlen, NULL, 0, pk)) != 0) { + printf("crypto_sign_open returned <%d>\n", ret_val); + return KAT_CRYPTO_FAILURE; + } + + if ( mlen != mlen1 ) { + printf("crypto_sign_open returned bad 'mlen': Got <%lu>, expected <%lu>\n", mlen1, mlen); + return KAT_CRYPTO_FAILURE; + } + + if ( memcmp(m, m1, mlen) ) { + printf("crypto_sign_open returned bad 'm' value\n"); + return KAT_CRYPTO_FAILURE; + } + + free(m); + free(m1); + free(sm); + + } while ( !done ); + + fclose(fp_req); + fclose(fp_rsp); + + return KAT_SUCCESS; +} + +// +// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.) +// +int +FindMarker(FILE *infile, const char *marker) +{ + char line[MAX_MARKER_LEN]; + int i, len; + int curr_line; + + len = (int)strlen(marker); + if ( len > MAX_MARKER_LEN-1 ) + len = MAX_MARKER_LEN-1; + + for ( i=0; i= '0') && (ch <= '9') ) + ich = ch - '0'; + else if ( (ch >= 'A') && (ch <= 'F') ) + ich = ch - 'A' + 10; + else if ( (ch >= 'a') && (ch <= 'f') ) + ich = ch - 'a' + 10; + else // shouldn't ever get here + ich = 0; + + for ( i=0; i> 4); + a[Length-1] = (a[Length-1] << 4) | ich; + } + else + return 0; + + return 1; +} + +void +fprintBstr(FILE *fp, char *s, unsigned char *a, unsigned long long l) +{ + unsigned long long i; + + fprintf(fp, "%s", s); + + for ( i=0; i +#include "rng.h" +#include +#include +#include + +AES256_CTR_DRBG_struct DRBG_ctx; + +void AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer); + +/* + seedexpander_init() + ctx - stores the current state of an instance of the seed expander + seed - a 32 byte random value + diversifier - an 8 byte diversifier + maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier + */ +int +seedexpander_init(AES_XOF_struct *ctx, + unsigned char *seed, + unsigned char *diversifier, + unsigned long maxlen) +{ + if ( maxlen >= 0x100000000 ) + return RNG_BAD_MAXLEN; + + ctx->length_remaining = maxlen; + + memcpy(ctx->key, seed, 32); + + memcpy(ctx->ctr, diversifier, 8); + ctx->ctr[11] = maxlen % 256; + maxlen >>= 8; + ctx->ctr[10] = maxlen % 256; + maxlen >>= 8; + ctx->ctr[9] = maxlen % 256; + maxlen >>= 8; + ctx->ctr[8] = maxlen % 256; + memset(ctx->ctr+12, 0x00, 4); + + ctx->buffer_pos = 16; + memset(ctx->buffer, 0x00, 16); + + return RNG_SUCCESS; +} + +/* + seedexpander() + ctx - stores the current state of an instance of the seed expander + x - returns the XOF data + xlen - number of bytes to return + */ +int +seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen) +{ + unsigned long offset; + + if ( x == NULL ) + return RNG_BAD_OUTBUF; + if ( xlen >= ctx->length_remaining ) + return RNG_BAD_REQ_LEN; + + ctx->length_remaining -= xlen; + + offset = 0; + while ( xlen > 0 ) { + if ( xlen <= (16-ctx->buffer_pos) ) { // buffer has what we need + memcpy(x+offset, ctx->buffer+ctx->buffer_pos, xlen); + ctx->buffer_pos += xlen; + + return RNG_SUCCESS; + } + + // take what's in the buffer + memcpy(x+offset, ctx->buffer+ctx->buffer_pos, 16-ctx->buffer_pos); + xlen -= 16-ctx->buffer_pos; + offset += 16-ctx->buffer_pos; + + AES256_ECB(ctx->key, ctx->ctr, ctx->buffer); + ctx->buffer_pos = 0; + + //increment the counter + for (int i=15; i>=12; i--) { + if ( ctx->ctr[i] == 0xff ) + ctx->ctr[i] = 0x00; + else { + ctx->ctr[i]++; + break; + } + } + + } + + return RNG_SUCCESS; +} + + +void handleErrors(void) +{ + ERR_print_errors_fp(stderr); + abort(); +} + +// Use whatever AES implementation you have. This uses AES from openSSL library +// key - 256-bit AES key +// ctr - a 128-bit plaintext value +// buffer - a 128-bit ciphertext value +void +AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer) +{ + EVP_CIPHER_CTX *ctx; + + int len; + + int ciphertext_len; + + /* Create and initialise the context */ + if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); + + if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL)) + handleErrors(); + + if(1 != EVP_EncryptUpdate(ctx, buffer, &len, ctr, 16)) + handleErrors(); + ciphertext_len = len; + + /* Clean up */ + EVP_CIPHER_CTX_free(ctx); +} + +void +randombytes_init(unsigned char *entropy_input, + unsigned char *personalization_string, + int security_strength) +{ + unsigned char seed_material[48]; + + memcpy(seed_material, entropy_input, 48); + if (personalization_string) + for (int i=0; i<48; i++) + seed_material[i] ^= personalization_string[i]; + memset(DRBG_ctx.Key, 0x00, 32); + memset(DRBG_ctx.V, 0x00, 16); + AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V); + DRBG_ctx.reseed_counter = 1; +} + +int +randombytes(unsigned char *x, unsigned long long xlen) +{ + unsigned char block[16]; + int i = 0; + + while ( xlen > 0 ) { + //increment V + for (int j=15; j>=0; j--) { + if ( DRBG_ctx.V[j] == 0xff ) + DRBG_ctx.V[j] = 0x00; + else { + DRBG_ctx.V[j]++; + break; + } + } + AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block); + if ( xlen > 15 ) { + memcpy(x+i, block, 16); + i += 16; + xlen -= 16; + } + else { + memcpy(x+i, block, xlen); + xlen = 0; + } + } + AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V); + DRBG_ctx.reseed_counter++; + + return RNG_SUCCESS; +} + +void +AES256_CTR_DRBG_Update(unsigned char *provided_data, + unsigned char *Key, + unsigned char *V) +{ + unsigned char temp[48]; + + for (int i=0; i<3; i++) { + //increment V + for (int j=15; j>=0; j--) { + if ( V[j] == 0xff ) + V[j] = 0x00; + else { + V[j]++; + break; + } + } + + AES256_ECB(Key, V, temp+16*i); + } + if ( provided_data != NULL ) + for (int i=0; i<48; i++) + temp[i] ^= provided_data[i]; + memcpy(Key, temp, 32); + memcpy(V, temp+32, 16); +} + + + + + + + + + diff --git a/ref/nistkat/rng.h b/ref/nistkat/rng.h new file mode 100644 index 0000000..577e263 --- /dev/null +++ b/ref/nistkat/rng.h @@ -0,0 +1,55 @@ +// +// rng.h +// +// Created by Bassham, Lawrence E (Fed) on 8/29/17. +// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. +// + +#ifndef rng_h +#define rng_h + +#include + +#define RNG_SUCCESS 0 +#define RNG_BAD_MAXLEN -1 +#define RNG_BAD_OUTBUF -2 +#define RNG_BAD_REQ_LEN -3 + +typedef struct { + unsigned char buffer[16]; + int buffer_pos; + unsigned long length_remaining; + unsigned char key[32]; + unsigned char ctr[16]; +} AES_XOF_struct; + +typedef struct { + unsigned char Key[32]; + unsigned char V[16]; + int reseed_counter; +} AES256_CTR_DRBG_struct; + + +void +AES256_CTR_DRBG_Update(unsigned char *provided_data, + unsigned char *Key, + unsigned char *V); + +int +seedexpander_init(AES_XOF_struct *ctx, + unsigned char *seed, + unsigned char *diversifier, + unsigned long maxlen); + +int +seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen); + +void +randombytes_init(unsigned char *entropy_input, + unsigned char *personalization_string, + int security_strength); + +int +randombytes(unsigned char *x, unsigned long long xlen); + +#endif /* rng_h */ diff --git a/ref/ntt.c b/ref/ntt.c new file mode 100644 index 0000000..5ea8b53 --- /dev/null +++ b/ref/ntt.c @@ -0,0 +1,98 @@ +#include +#include "params.h" +#include "ntt.h" +#include "reduce.h" + +static const int32_t zetas[N] = { + 0, 25847, -2608894, -518909, 237124, -777960, -876248, 466468, + 1826347, 2353451, -359251, -2091905, 3119733, -2884855, 3111497, 2680103, + 2725464, 1024112, -1079900, 3585928, -549488, -1119584, 2619752, -2108549, + -2118186, -3859737, -1399561, -3277672, 1757237, -19422, 4010497, 280005, + 2706023, 95776, 3077325, 3530437, -1661693, -3592148, -2537516, 3915439, + -3861115, -3043716, 3574422, -2867647, 3539968, -300467, 2348700, -539299, + -1699267, -1643818, 3505694, -3821735, 3507263, -2140649, -1600420, 3699596, + 811944, 531354, 954230, 3881043, 3900724, -2556880, 2071892, -2797779, + -3930395, -1528703, -3677745, -3041255, -1452451, 3475950, 2176455, -1585221, + -1257611, 1939314, -4083598, -1000202, -3190144, -3157330, -3632928, 126922, + 3412210, -983419, 2147896, 2715295, -2967645, -3693493, -411027, -2477047, + -671102, -1228525, -22981, -1308169, -381987, 1349076, 1852771, -1430430, + -3343383, 264944, 508951, 3097992, 44288, -1100098, 904516, 3958618, + -3724342, -8578, 1653064, -3249728, 2389356, -210977, 759969, -1316856, + 189548, -3553272, 3159746, -1851402, -2409325, -177440, 1315589, 1341330, + 1285669, -1584928, -812732, -1439742, -3019102, -3881060, -3628969, 3839961, + 2091667, 3407706, 2316500, 3817976, -3342478, 2244091, -2446433, -3562462, + 266997, 2434439, -1235728, 3513181, -3520352, -3759364, -1197226, -3193378, + 900702, 1859098, 909542, 819034, 495491, -1613174, -43260, -522500, + -655327, -3122442, 2031748, 3207046, -3556995, -525098, -768622, -3595838, + 342297, 286988, -2437823, 4108315, 3437287, -3342277, 1735879, 203044, + 2842341, 2691481, -2590150, 1265009, 4055324, 1247620, 2486353, 1595974, + -3767016, 1250494, 2635921, -3548272, -2994039, 1869119, 1903435, -1050970, + -1333058, 1237275, -3318210, -1430225, -451100, 1312455, 3306115, -1962642, + -1279661, 1917081, -2546312, -1374803, 1500165, 777191, 2235880, 3406031, + -542412, -2831860, -1671176, -1846953, -2584293, -3724270, 594136, -3776993, + -2013608, 2432395, 2454455, -164721, 1957272, 3369112, 185531, -1207385, + -3183426, 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107, + -3038916, 3523897, 3866901, 269760, 2213111, -975884, 1717735, 472078, + -426683, 1723600, -1803090, 1910376, -1667432, -1104333, -260646, -3833893, + -2939036, -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, + -554416, 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782 +}; + +/************************************************* +* Name: ntt +* +* Description: Forward NTT, in-place. No modular reduction is performed after +* additions or subtractions. Output vector is in bitreversed order. +* +* Arguments: - uint32_t p[N]: input/output coefficient array +**************************************************/ +void ntt(int32_t a[N]) { + unsigned int len, start, j, k; + int32_t zeta, t; + + k = 0; + for(len = 128; len > 0; len >>= 1) { + for(start = 0; start < N; start = j + len) { + zeta = zetas[++k]; + for(j = start; j < start + len; ++j) { + t = montgomery_reduce((int64_t)zeta * a[j + len]); + a[j + len] = a[j] - t; + a[j] = a[j] + t; + } + } + } +} + +/************************************************* +* Name: invntt_tomont +* +* Description: Inverse NTT and multiplication by Montgomery factor 2^32. +* In-place. No modular reductions after additions or +* subtractions; input coefficients need to be smaller than +* Q in absolute value. Output coefficient are smaller than Q in +* absolute value. +* +* Arguments: - uint32_t p[N]: input/output coefficient array +**************************************************/ +void invntt_tomont(int32_t a[N]) { + unsigned int start, len, j, k; + int32_t t, zeta; + const int32_t f = 41978; // mont^2/256 + + k = 256; + for(len = 1; len < N; len <<= 1) { + for(start = 0; start < N; start = j + len) { + zeta = -zetas[--k]; + for(j = start; j < start + len; ++j) { + t = a[j]; + a[j] = t + a[j + len]; + a[j + len] = t - a[j + len]; + a[j + len] = montgomery_reduce((int64_t)zeta * a[j + len]); + } + } + } + + for(j = 0; j < N; ++j) { + a[j] = montgomery_reduce((int64_t)f * a[j]); + } +} diff --git a/ref/ntt.h b/ref/ntt.h new file mode 100644 index 0000000..731132d --- /dev/null +++ b/ref/ntt.h @@ -0,0 +1,13 @@ +#ifndef NTT_H +#define NTT_H + +#include +#include "params.h" + +#define ntt DILITHIUM_NAMESPACE(ntt) +void ntt(int32_t a[N]); + +#define invntt_tomont DILITHIUM_NAMESPACE(invntt_tomont) +void invntt_tomont(int32_t a[N]); + +#endif diff --git a/ref/packing.c b/ref/packing.c new file mode 100644 index 0000000..039a686 --- /dev/null +++ b/ref/packing.c @@ -0,0 +1,237 @@ +#include "params.h" +#include "packing.h" +#include "polyvec.h" +#include "poly.h" + +/************************************************* +* Name: pack_pk +* +* Description: Bit-pack public key pk = (rho, t1). +* +* Arguments: - uint8_t pk[]: output byte array +* - const uint8_t rho[]: byte array containing rho +* - const polyveck *t1: pointer to vector t1 +**************************************************/ +void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], + const uint8_t rho[SEEDBYTES], + const polyveck *t1) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + pk[i] = rho[i]; + pk += SEEDBYTES; + + for(i = 0; i < K; ++i) + polyt1_pack(pk + i*POLYT1_PACKEDBYTES, &t1->vec[i]); +} + +/************************************************* +* Name: unpack_pk +* +* Description: Unpack public key pk = (rho, t1). +* +* Arguments: - const uint8_t rho[]: output byte array for rho +* - const polyveck *t1: pointer to output vector t1 +* - uint8_t pk[]: byte array containing bit-packed pk +**************************************************/ +void unpack_pk(uint8_t rho[SEEDBYTES], + polyveck *t1, + const uint8_t pk[CRYPTO_PUBLICKEYBYTES]) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + rho[i] = pk[i]; + pk += SEEDBYTES; + + for(i = 0; i < K; ++i) + polyt1_unpack(&t1->vec[i], pk + i*POLYT1_PACKEDBYTES); +} + +/************************************************* +* Name: pack_sk +* +* Description: Bit-pack secret key sk = (rho, tr, key, t0, s1, s2). +* +* Arguments: - uint8_t sk[]: output byte array +* - const uint8_t rho[]: byte array containing rho +* - const uint8_t tr[]: byte array containing tr +* - const uint8_t key[]: byte array containing key +* - const polyveck *t0: pointer to vector t0 +* - const polyvecl *s1: pointer to vector s1 +* - const polyveck *s2: pointer to vector s2 +**************************************************/ +void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], + const uint8_t rho[SEEDBYTES], + const uint8_t tr[TRBYTES], + const uint8_t key[SEEDBYTES], + const polyveck *t0, + const polyvecl *s1, + const polyveck *s2) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + sk[i] = rho[i]; + sk += SEEDBYTES; + + for(i = 0; i < SEEDBYTES; ++i) + sk[i] = key[i]; + sk += SEEDBYTES; + + for(i = 0; i < TRBYTES; ++i) + sk[i] = tr[i]; + sk += TRBYTES; + + for(i = 0; i < L; ++i) + polyeta_pack(sk + i*POLYETA_PACKEDBYTES, &s1->vec[i]); + sk += L*POLYETA_PACKEDBYTES; + + for(i = 0; i < K; ++i) + polyeta_pack(sk + i*POLYETA_PACKEDBYTES, &s2->vec[i]); + sk += K*POLYETA_PACKEDBYTES; + + for(i = 0; i < K; ++i) + polyt0_pack(sk + i*POLYT0_PACKEDBYTES, &t0->vec[i]); +} + +/************************************************* +* Name: unpack_sk +* +* Description: Unpack secret key sk = (rho, tr, key, t0, s1, s2). +* +* Arguments: - const uint8_t rho[]: output byte array for rho +* - const uint8_t tr[]: output byte array for tr +* - const uint8_t key[]: output byte array for key +* - const polyveck *t0: pointer to output vector t0 +* - const polyvecl *s1: pointer to output vector s1 +* - const polyveck *s2: pointer to output vector s2 +* - uint8_t sk[]: byte array containing bit-packed sk +**************************************************/ +void unpack_sk(uint8_t rho[SEEDBYTES], + uint8_t tr[TRBYTES], + uint8_t key[SEEDBYTES], + polyveck *t0, + polyvecl *s1, + polyveck *s2, + const uint8_t sk[CRYPTO_SECRETKEYBYTES]) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + rho[i] = sk[i]; + sk += SEEDBYTES; + + for(i = 0; i < SEEDBYTES; ++i) + key[i] = sk[i]; + sk += SEEDBYTES; + + for(i = 0; i < TRBYTES; ++i) + tr[i] = sk[i]; + sk += TRBYTES; + + for(i=0; i < L; ++i) + polyeta_unpack(&s1->vec[i], sk + i*POLYETA_PACKEDBYTES); + sk += L*POLYETA_PACKEDBYTES; + + for(i=0; i < K; ++i) + polyeta_unpack(&s2->vec[i], sk + i*POLYETA_PACKEDBYTES); + sk += K*POLYETA_PACKEDBYTES; + + for(i=0; i < K; ++i) + polyt0_unpack(&t0->vec[i], sk + i*POLYT0_PACKEDBYTES); +} + +/************************************************* +* Name: pack_sig +* +* Description: Bit-pack signature sig = (c, z, h). +* +* Arguments: - uint8_t sig[]: output byte array +* - const uint8_t *c: pointer to challenge hash length SEEDBYTES +* - const polyvecl *z: pointer to vector z +* - const polyveck *h: pointer to hint vector h +**************************************************/ +void pack_sig(uint8_t sig[CRYPTO_BYTES], + const uint8_t c[CTILDEBYTES], + const polyvecl *z, + const polyveck *h) +{ + unsigned int i, j, k; + + for(i=0; i < CTILDEBYTES; ++i) + sig[i] = c[i]; + sig += CTILDEBYTES; + + for(i = 0; i < L; ++i) + polyz_pack(sig + i*POLYZ_PACKEDBYTES, &z->vec[i]); + sig += L*POLYZ_PACKEDBYTES; + + /* Encode h */ + for(i = 0; i < OMEGA + K; ++i) + sig[i] = 0; + + k = 0; + for(i = 0; i < K; ++i) { + for(j = 0; j < N; ++j) + if(h->vec[i].coeffs[j] != 0) + sig[k++] = j; + + sig[OMEGA + i] = k; + } +} + +/************************************************* +* Name: unpack_sig +* +* Description: Unpack signature sig = (c, z, h). +* +* Arguments: - uint8_t *c: pointer to output challenge hash +* - polyvecl *z: pointer to output vector z +* - polyveck *h: pointer to output hint vector h +* - const uint8_t sig[]: byte array containing +* bit-packed signature +* +* Returns 1 in case of malformed signature; otherwise 0. +**************************************************/ +int unpack_sig(uint8_t c[CTILDEBYTES], + polyvecl *z, + polyveck *h, + const uint8_t sig[CRYPTO_BYTES]) +{ + unsigned int i, j, k; + + for(i = 0; i < CTILDEBYTES; ++i) + c[i] = sig[i]; + sig += CTILDEBYTES; + + for(i = 0; i < L; ++i) + polyz_unpack(&z->vec[i], sig + i*POLYZ_PACKEDBYTES); + sig += L*POLYZ_PACKEDBYTES; + + /* Decode h */ + k = 0; + for(i = 0; i < K; ++i) { + for(j = 0; j < N; ++j) + h->vec[i].coeffs[j] = 0; + + if(sig[OMEGA + i] < k || sig[OMEGA + i] > OMEGA) + return 1; + + for(j = k; j < sig[OMEGA + i]; ++j) { + /* Coefficients are ordered for strong unforgeability */ + if(j > k && sig[j] <= sig[j-1]) return 1; + h->vec[i].coeffs[sig[j]] = 1; + } + + k = sig[OMEGA + i]; + } + + /* Extra indices are zero for strong unforgeability */ + for(j = k; j < OMEGA; ++j) + if(sig[j]) + return 1; + + return 0; +} diff --git a/ref/packing.h b/ref/packing.h new file mode 100644 index 0000000..8e47728 --- /dev/null +++ b/ref/packing.h @@ -0,0 +1,38 @@ +#ifndef PACKING_H +#define PACKING_H + +#include +#include "params.h" +#include "polyvec.h" + +#define pack_pk DILITHIUM_NAMESPACE(pack_pk) +void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], const uint8_t rho[SEEDBYTES], const polyveck *t1); + +#define pack_sk DILITHIUM_NAMESPACE(pack_sk) +void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], + const uint8_t rho[SEEDBYTES], + const uint8_t tr[TRBYTES], + const uint8_t key[SEEDBYTES], + const polyveck *t0, + const polyvecl *s1, + const polyveck *s2); + +#define pack_sig DILITHIUM_NAMESPACE(pack_sig) +void pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c[CTILDEBYTES], const polyvecl *z, const polyveck *h); + +#define unpack_pk DILITHIUM_NAMESPACE(unpack_pk) +void unpack_pk(uint8_t rho[SEEDBYTES], polyveck *t1, const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); + +#define unpack_sk DILITHIUM_NAMESPACE(unpack_sk) +void unpack_sk(uint8_t rho[SEEDBYTES], + uint8_t tr[TRBYTES], + uint8_t key[SEEDBYTES], + polyveck *t0, + polyvecl *s1, + polyveck *s2, + const uint8_t sk[CRYPTO_SECRETKEYBYTES]); + +#define unpack_sig DILITHIUM_NAMESPACE(unpack_sig) +int unpack_sig(uint8_t c[CTILDEBYTES], polyvecl *z, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); + +#endif diff --git a/ref/params.h b/ref/params.h new file mode 100644 index 0000000..1e8a7b5 --- /dev/null +++ b/ref/params.h @@ -0,0 +1,80 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#include "config.h" + +#define SEEDBYTES 32 +#define CRHBYTES 64 +#define TRBYTES 64 +#define RNDBYTES 32 +#define N 256 +#define Q 8380417 +#define D 13 +#define ROOT_OF_UNITY 1753 + +#if DILITHIUM_MODE == 2 +#define K 4 +#define L 4 +#define ETA 2 +#define TAU 39 +#define BETA 78 +#define GAMMA1 (1 << 17) +#define GAMMA2 ((Q-1)/88) +#define OMEGA 80 +#define CTILDEBYTES 32 + +#elif DILITHIUM_MODE == 3 +#define K 6 +#define L 5 +#define ETA 4 +#define TAU 49 +#define BETA 196 +#define GAMMA1 (1 << 19) +#define GAMMA2 ((Q-1)/32) +#define OMEGA 55 +#define CTILDEBYTES 48 + +#elif DILITHIUM_MODE == 5 +#define K 8 +#define L 7 +#define ETA 2 +#define TAU 60 +#define BETA 120 +#define GAMMA1 (1 << 19) +#define GAMMA2 ((Q-1)/32) +#define OMEGA 75 +#define CTILDEBYTES 64 + +#endif + +#define POLYT1_PACKEDBYTES 320 +#define POLYT0_PACKEDBYTES 416 +#define POLYVECH_PACKEDBYTES (OMEGA + K) + +#if GAMMA1 == (1 << 17) +#define POLYZ_PACKEDBYTES 576 +#elif GAMMA1 == (1 << 19) +#define POLYZ_PACKEDBYTES 640 +#endif + +#if GAMMA2 == (Q-1)/88 +#define POLYW1_PACKEDBYTES 192 +#elif GAMMA2 == (Q-1)/32 +#define POLYW1_PACKEDBYTES 128 +#endif + +#if ETA == 2 +#define POLYETA_PACKEDBYTES 96 +#elif ETA == 4 +#define POLYETA_PACKEDBYTES 128 +#endif + +#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K*POLYT1_PACKEDBYTES) +#define CRYPTO_SECRETKEYBYTES (2*SEEDBYTES \ + + TRBYTES \ + + L*POLYETA_PACKEDBYTES \ + + K*POLYETA_PACKEDBYTES \ + + K*POLYT0_PACKEDBYTES) +#define CRYPTO_BYTES (CTILDEBYTES + L*POLYZ_PACKEDBYTES + POLYVECH_PACKEDBYTES) + +#endif diff --git a/ref/poly.c b/ref/poly.c new file mode 100644 index 0000000..0db4f42 --- /dev/null +++ b/ref/poly.c @@ -0,0 +1,907 @@ +#include +#include "params.h" +#include "poly.h" +#include "ntt.h" +#include "reduce.h" +#include "rounding.h" +#include "symmetric.h" + +#ifdef DBENCH +#include "test/cpucycles.h" +extern const uint64_t timing_overhead; +extern uint64_t *tred, *tadd, *tmul, *tround, *tsample, *tpack; +#define DBENCH_START() uint64_t time = cpucycles() +#define DBENCH_STOP(t) t += cpucycles() - time - timing_overhead +#else +#define DBENCH_START() +#define DBENCH_STOP(t) +#endif + +/************************************************* +* Name: poly_reduce +* +* Description: Inplace reduction of all coefficients of polynomial to +* representative in [-6283008,6283008]. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_reduce(poly *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + a->coeffs[i] = reduce32(a->coeffs[i]); + + DBENCH_STOP(*tred); +} + +/************************************************* +* Name: poly_caddq +* +* Description: For all coefficients of in/out polynomial add Q if +* coefficient is negative. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_caddq(poly *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + a->coeffs[i] = caddq(a->coeffs[i]); + + DBENCH_STOP(*tred); +} + +/************************************************* +* Name: poly_add +* +* Description: Add polynomials. No modular reduction is performed. +* +* Arguments: - poly *c: pointer to output polynomial +* - const poly *a: pointer to first summand +* - const poly *b: pointer to second summand +**************************************************/ +void poly_add(poly *c, const poly *a, const poly *b) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; + + DBENCH_STOP(*tadd); +} + +/************************************************* +* Name: poly_sub +* +* Description: Subtract polynomials. No modular reduction is +* performed. +* +* Arguments: - poly *c: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial to be +* subtraced from first input polynomial +**************************************************/ +void poly_sub(poly *c, const poly *a, const poly *b) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; + + DBENCH_STOP(*tadd); +} + +/************************************************* +* Name: poly_shiftl +* +* Description: Multiply polynomial by 2^D without modular reduction. Assumes +* input coefficients to be less than 2^{31-D} in absolute value. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_shiftl(poly *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + a->coeffs[i] <<= D; + + DBENCH_STOP(*tmul); +} + +/************************************************* +* Name: poly_ntt +* +* Description: Inplace forward NTT. Coefficients can grow by +* 8*Q in absolute value. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_ntt(poly *a) { + DBENCH_START(); + + ntt(a->coeffs); + + DBENCH_STOP(*tmul); +} + +/************************************************* +* Name: poly_invntt_tomont +* +* Description: Inplace inverse NTT and multiplication by 2^{32}. +* Input coefficients need to be less than Q in absolute +* value and output coefficients are again bounded by Q. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_invntt_tomont(poly *a) { + DBENCH_START(); + + invntt_tomont(a->coeffs); + + DBENCH_STOP(*tmul); +} + +/************************************************* +* Name: poly_pointwise_montgomery +* +* Description: Pointwise multiplication of polynomials in NTT domain +* representation and multiplication of resulting polynomial +* by 2^{-32}. +* +* Arguments: - poly *c: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); + + DBENCH_STOP(*tmul); +} + +/************************************************* +* Name: poly_power2round +* +* Description: For all coefficients c of the input polynomial, +* compute c0, c1 such that c mod Q = c1*2^D + c0 +* with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be +* standard representatives. +* +* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 +* - poly *a0: pointer to output polynomial with coefficients c0 +* - const poly *a: pointer to input polynomial +**************************************************/ +void poly_power2round(poly *a1, poly *a0, const poly *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + a1->coeffs[i] = power2round(&a0->coeffs[i], a->coeffs[i]); + + DBENCH_STOP(*tround); +} + +/************************************************* +* Name: poly_decompose +* +* Description: For all coefficients c of the input polynomial, +* compute high and low bits c0, c1 such c mod Q = c1*ALPHA + c0 +* with -ALPHA/2 < c0 <= ALPHA/2 except c1 = (Q-1)/ALPHA where we +* set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0. +* Assumes coefficients to be standard representatives. +* +* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 +* - poly *a0: pointer to output polynomial with coefficients c0 +* - const poly *a: pointer to input polynomial +**************************************************/ +void poly_decompose(poly *a1, poly *a0, const poly *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + a1->coeffs[i] = decompose(&a0->coeffs[i], a->coeffs[i]); + + DBENCH_STOP(*tround); +} + +/************************************************* +* Name: poly_make_hint +* +* Description: Compute hint polynomial. The coefficients of which indicate +* whether the low bits of the corresponding coefficient of +* the input polynomial overflow into the high bits. +* +* Arguments: - poly *h: pointer to output hint polynomial +* - const poly *a0: pointer to low part of input polynomial +* - const poly *a1: pointer to high part of input polynomial +* +* Returns number of 1 bits. +**************************************************/ +unsigned int poly_make_hint(poly *h, const poly *a0, const poly *a1) { + unsigned int i, s = 0; + DBENCH_START(); + + for(i = 0; i < N; ++i) { + h->coeffs[i] = make_hint(a0->coeffs[i], a1->coeffs[i]); + s += h->coeffs[i]; + } + + DBENCH_STOP(*tround); + return s; +} + +/************************************************* +* Name: poly_use_hint +* +* Description: Use hint polynomial to correct the high bits of a polynomial. +* +* Arguments: - poly *b: pointer to output polynomial with corrected high bits +* - const poly *a: pointer to input polynomial +* - const poly *h: pointer to input hint polynomial +**************************************************/ +void poly_use_hint(poly *b, const poly *a, const poly *h) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + b->coeffs[i] = use_hint(a->coeffs[i], h->coeffs[i]); + + DBENCH_STOP(*tround); +} + +/************************************************* +* Name: poly_chknorm +* +* Description: Check infinity norm of polynomial against given bound. +* Assumes input coefficients were reduced by reduce32(). +* +* Arguments: - const poly *a: pointer to polynomial +* - int32_t B: norm bound +* +* Returns 0 if norm is strictly smaller than B <= (Q-1)/8 and 1 otherwise. +**************************************************/ +int poly_chknorm(const poly *a, int32_t B) { + unsigned int i; + int32_t t; + DBENCH_START(); + + if(B > (Q-1)/8) + return 1; + + /* It is ok to leak which coefficient violates the bound since + the probability for each coefficient is independent of secret + data but we must not leak the sign of the centralized representative. */ + for(i = 0; i < N; ++i) { + /* Absolute value */ + t = a->coeffs[i] >> 31; + t = a->coeffs[i] - (t & 2*a->coeffs[i]); + + if(t >= B) { + DBENCH_STOP(*tsample); + return 1; + } + } + + DBENCH_STOP(*tsample); + return 0; +} + +/************************************************* +* Name: rej_uniform +* +* Description: Sample uniformly random coefficients in [0, Q-1] by +* performing rejection sampling on array of random bytes. +* +* Arguments: - int32_t *a: pointer to output array (allocated) +* - unsigned int len: number of coefficients to be sampled +* - const uint8_t *buf: array of random bytes +* - unsigned int buflen: length of array of random bytes +* +* Returns number of sampled coefficients. Can be smaller than len if not enough +* random bytes were given. +**************************************************/ +static unsigned int rej_uniform(int32_t *a, + unsigned int len, + const uint8_t *buf, + unsigned int buflen) +{ + unsigned int ctr, pos; + uint32_t t; + DBENCH_START(); + + ctr = pos = 0; + while(ctr < len && pos + 3 <= buflen) { + t = buf[pos++]; + t |= (uint32_t)buf[pos++] << 8; + t |= (uint32_t)buf[pos++] << 16; + t &= 0x7FFFFF; + + if(t < Q) + a[ctr++] = t; + } + + DBENCH_STOP(*tsample); + return ctr; +} + +/************************************************* +* Name: poly_uniform +* +* Description: Sample polynomial with uniformly random coefficients +* in [0,Q-1] by performing rejection sampling on the +* output stream of SHAKE128(seed|nonce) +* +* Arguments: - poly *a: pointer to output polynomial +* - const uint8_t seed[]: byte array with seed of length SEEDBYTES +* - uint16_t nonce: 2-byte nonce +**************************************************/ +#define POLY_UNIFORM_NBLOCKS ((768 + STREAM128_BLOCKBYTES - 1)/STREAM128_BLOCKBYTES) +void poly_uniform(poly *a, + const uint8_t seed[SEEDBYTES], + uint16_t nonce) +{ + unsigned int i, ctr, off; + unsigned int buflen = POLY_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES + 2]; + stream128_state state; + + stream128_init(&state, seed, nonce); + stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); + + ctr = rej_uniform(a->coeffs, N, buf, buflen); + + while(ctr < N) { + off = buflen % 3; + for(i = 0; i < off; ++i) + buf[i] = buf[buflen - off + i]; + + stream128_squeezeblocks(buf + off, 1, &state); + buflen = STREAM128_BLOCKBYTES + off; + ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen); + } +} + +/************************************************* +* Name: rej_eta +* +* Description: Sample uniformly random coefficients in [-ETA, ETA] by +* performing rejection sampling on array of random bytes. +* +* Arguments: - int32_t *a: pointer to output array (allocated) +* - unsigned int len: number of coefficients to be sampled +* - const uint8_t *buf: array of random bytes +* - unsigned int buflen: length of array of random bytes +* +* Returns number of sampled coefficients. Can be smaller than len if not enough +* random bytes were given. +**************************************************/ +static unsigned int rej_eta(int32_t *a, + unsigned int len, + const uint8_t *buf, + unsigned int buflen) +{ + unsigned int ctr, pos; + uint32_t t0, t1; + DBENCH_START(); + + ctr = pos = 0; + while(ctr < len && pos < buflen) { + t0 = buf[pos] & 0x0F; + t1 = buf[pos++] >> 4; + +#if ETA == 2 + if(t0 < 15) { + t0 = t0 - (205*t0 >> 10)*5; + a[ctr++] = 2 - t0; + } + if(t1 < 15 && ctr < len) { + t1 = t1 - (205*t1 >> 10)*5; + a[ctr++] = 2 - t1; + } +#elif ETA == 4 + if(t0 < 9) + a[ctr++] = 4 - t0; + if(t1 < 9 && ctr < len) + a[ctr++] = 4 - t1; +#endif + } + + DBENCH_STOP(*tsample); + return ctr; +} + +/************************************************* +* Name: poly_uniform_eta +* +* Description: Sample polynomial with uniformly random coefficients +* in [-ETA,ETA] by performing rejection sampling on the +* output stream from SHAKE256(seed|nonce) +* +* Arguments: - poly *a: pointer to output polynomial +* - const uint8_t seed[]: byte array with seed of length CRHBYTES +* - uint16_t nonce: 2-byte nonce +**************************************************/ +#if ETA == 2 +#define POLY_UNIFORM_ETA_NBLOCKS ((136 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) +#elif ETA == 4 +#define POLY_UNIFORM_ETA_NBLOCKS ((227 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) +#endif +void poly_uniform_eta(poly *a, + const uint8_t seed[CRHBYTES], + uint16_t nonce) +{ + unsigned int ctr; + unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS*STREAM256_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS*STREAM256_BLOCKBYTES]; + stream256_state state; + + stream256_init(&state, seed, nonce); + stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state); + + ctr = rej_eta(a->coeffs, N, buf, buflen); + + while(ctr < N) { + stream256_squeezeblocks(buf, 1, &state); + ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES); + } +} + +/************************************************* +* Name: poly_uniform_gamma1m1 +* +* Description: Sample polynomial with uniformly random coefficients +* in [-(GAMMA1 - 1), GAMMA1] by unpacking output stream +* of SHAKE256(seed|nonce) +* +* Arguments: - poly *a: pointer to output polynomial +* - const uint8_t seed[]: byte array with seed of length CRHBYTES +* - uint16_t nonce: 16-bit nonce +**************************************************/ +#define POLY_UNIFORM_GAMMA1_NBLOCKS ((POLYZ_PACKEDBYTES + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) +void poly_uniform_gamma1(poly *a, + const uint8_t seed[CRHBYTES], + uint16_t nonce) +{ + uint8_t buf[POLY_UNIFORM_GAMMA1_NBLOCKS*STREAM256_BLOCKBYTES]; + stream256_state state; + + stream256_init(&state, seed, nonce); + stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1_NBLOCKS, &state); + polyz_unpack(a, buf); +} + +/************************************************* +* Name: challenge +* +* Description: Implementation of H. Samples polynomial with TAU nonzero +* coefficients in {-1,1} using the output stream of +* SHAKE256(seed). +* +* Arguments: - poly *c: pointer to output polynomial +* - const uint8_t mu[]: byte array containing seed of length CTILDEBYTES +**************************************************/ +void poly_challenge(poly *c, const uint8_t seed[CTILDEBYTES]) { + unsigned int i, b, pos; + uint64_t signs; + uint8_t buf[SHAKE256_RATE]; + keccak_state state; + + shake256_init(&state); + shake256_absorb(&state, seed, CTILDEBYTES); + shake256_finalize(&state); + shake256_squeezeblocks(buf, 1, &state); + + signs = 0; + for(i = 0; i < 8; ++i) + signs |= (uint64_t)buf[i] << 8*i; + pos = 8; + + for(i = 0; i < N; ++i) + c->coeffs[i] = 0; + for(i = N-TAU; i < N; ++i) { + do { + if(pos >= SHAKE256_RATE) { + shake256_squeezeblocks(buf, 1, &state); + pos = 0; + } + + b = buf[pos++]; + } while(b > i); + + c->coeffs[i] = c->coeffs[b]; + c->coeffs[b] = 1 - 2*(signs & 1); + signs >>= 1; + } +} + +/************************************************* +* Name: polyeta_pack +* +* Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYETA_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyeta_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint8_t t[8]; + DBENCH_START(); + +#if ETA == 2 + for(i = 0; i < N/8; ++i) { + t[0] = ETA - a->coeffs[8*i+0]; + t[1] = ETA - a->coeffs[8*i+1]; + t[2] = ETA - a->coeffs[8*i+2]; + t[3] = ETA - a->coeffs[8*i+3]; + t[4] = ETA - a->coeffs[8*i+4]; + t[5] = ETA - a->coeffs[8*i+5]; + t[6] = ETA - a->coeffs[8*i+6]; + t[7] = ETA - a->coeffs[8*i+7]; + + r[3*i+0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); + r[3*i+1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); + r[3*i+2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + } +#elif ETA == 4 + for(i = 0; i < N/2; ++i) { + t[0] = ETA - a->coeffs[2*i+0]; + t[1] = ETA - a->coeffs[2*i+1]; + r[i] = t[0] | (t[1] << 4); + } +#endif + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyeta_unpack +* +* Description: Unpack polynomial with coefficients in [-ETA,ETA]. +* +* Arguments: - poly *r: pointer to output polynomial +* - const uint8_t *a: byte array with bit-packed polynomial +**************************************************/ +void polyeta_unpack(poly *r, const uint8_t *a) { + unsigned int i; + DBENCH_START(); + +#if ETA == 2 + for(i = 0; i < N/8; ++i) { + r->coeffs[8*i+0] = (a[3*i+0] >> 0) & 7; + r->coeffs[8*i+1] = (a[3*i+0] >> 3) & 7; + r->coeffs[8*i+2] = ((a[3*i+0] >> 6) | (a[3*i+1] << 2)) & 7; + r->coeffs[8*i+3] = (a[3*i+1] >> 1) & 7; + r->coeffs[8*i+4] = (a[3*i+1] >> 4) & 7; + r->coeffs[8*i+5] = ((a[3*i+1] >> 7) | (a[3*i+2] << 1)) & 7; + r->coeffs[8*i+6] = (a[3*i+2] >> 2) & 7; + r->coeffs[8*i+7] = (a[3*i+2] >> 5) & 7; + + r->coeffs[8*i+0] = ETA - r->coeffs[8*i+0]; + r->coeffs[8*i+1] = ETA - r->coeffs[8*i+1]; + r->coeffs[8*i+2] = ETA - r->coeffs[8*i+2]; + r->coeffs[8*i+3] = ETA - r->coeffs[8*i+3]; + r->coeffs[8*i+4] = ETA - r->coeffs[8*i+4]; + r->coeffs[8*i+5] = ETA - r->coeffs[8*i+5]; + r->coeffs[8*i+6] = ETA - r->coeffs[8*i+6]; + r->coeffs[8*i+7] = ETA - r->coeffs[8*i+7]; + } +#elif ETA == 4 + for(i = 0; i < N/2; ++i) { + r->coeffs[2*i+0] = a[i] & 0x0F; + r->coeffs[2*i+1] = a[i] >> 4; + r->coeffs[2*i+0] = ETA - r->coeffs[2*i+0]; + r->coeffs[2*i+1] = ETA - r->coeffs[2*i+1]; + } +#endif + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyt1_pack +* +* Description: Bit-pack polynomial t1 with coefficients fitting in 10 bits. +* Input coefficients are assumed to be standard representatives. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYT1_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyt1_pack(uint8_t *r, const poly *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N/4; ++i) { + r[5*i+0] = (a->coeffs[4*i+0] >> 0); + r[5*i+1] = (a->coeffs[4*i+0] >> 8) | (a->coeffs[4*i+1] << 2); + r[5*i+2] = (a->coeffs[4*i+1] >> 6) | (a->coeffs[4*i+2] << 4); + r[5*i+3] = (a->coeffs[4*i+2] >> 4) | (a->coeffs[4*i+3] << 6); + r[5*i+4] = (a->coeffs[4*i+3] >> 2); + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyt1_unpack +* +* Description: Unpack polynomial t1 with 10-bit coefficients. +* Output coefficients are standard representatives. +* +* Arguments: - poly *r: pointer to output polynomial +* - const uint8_t *a: byte array with bit-packed polynomial +**************************************************/ +void polyt1_unpack(poly *r, const uint8_t *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N/4; ++i) { + r->coeffs[4*i+0] = ((a[5*i+0] >> 0) | ((uint32_t)a[5*i+1] << 8)) & 0x3FF; + r->coeffs[4*i+1] = ((a[5*i+1] >> 2) | ((uint32_t)a[5*i+2] << 6)) & 0x3FF; + r->coeffs[4*i+2] = ((a[5*i+2] >> 4) | ((uint32_t)a[5*i+3] << 4)) & 0x3FF; + r->coeffs[4*i+3] = ((a[5*i+3] >> 6) | ((uint32_t)a[5*i+4] << 2)) & 0x3FF; + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyt0_pack +* +* Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYT0_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyt0_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint32_t t[8]; + DBENCH_START(); + + for(i = 0; i < N/8; ++i) { + t[0] = (1 << (D-1)) - a->coeffs[8*i+0]; + t[1] = (1 << (D-1)) - a->coeffs[8*i+1]; + t[2] = (1 << (D-1)) - a->coeffs[8*i+2]; + t[3] = (1 << (D-1)) - a->coeffs[8*i+3]; + t[4] = (1 << (D-1)) - a->coeffs[8*i+4]; + t[5] = (1 << (D-1)) - a->coeffs[8*i+5]; + t[6] = (1 << (D-1)) - a->coeffs[8*i+6]; + t[7] = (1 << (D-1)) - a->coeffs[8*i+7]; + + r[13*i+ 0] = t[0]; + r[13*i+ 1] = t[0] >> 8; + r[13*i+ 1] |= t[1] << 5; + r[13*i+ 2] = t[1] >> 3; + r[13*i+ 3] = t[1] >> 11; + r[13*i+ 3] |= t[2] << 2; + r[13*i+ 4] = t[2] >> 6; + r[13*i+ 4] |= t[3] << 7; + r[13*i+ 5] = t[3] >> 1; + r[13*i+ 6] = t[3] >> 9; + r[13*i+ 6] |= t[4] << 4; + r[13*i+ 7] = t[4] >> 4; + r[13*i+ 8] = t[4] >> 12; + r[13*i+ 8] |= t[5] << 1; + r[13*i+ 9] = t[5] >> 7; + r[13*i+ 9] |= t[6] << 6; + r[13*i+10] = t[6] >> 2; + r[13*i+11] = t[6] >> 10; + r[13*i+11] |= t[7] << 3; + r[13*i+12] = t[7] >> 5; + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyt0_unpack +* +* Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. +* +* Arguments: - poly *r: pointer to output polynomial +* - const uint8_t *a: byte array with bit-packed polynomial +**************************************************/ +void polyt0_unpack(poly *r, const uint8_t *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N/8; ++i) { + r->coeffs[8*i+0] = a[13*i+0]; + r->coeffs[8*i+0] |= (uint32_t)a[13*i+1] << 8; + r->coeffs[8*i+0] &= 0x1FFF; + + r->coeffs[8*i+1] = a[13*i+1] >> 5; + r->coeffs[8*i+1] |= (uint32_t)a[13*i+2] << 3; + r->coeffs[8*i+1] |= (uint32_t)a[13*i+3] << 11; + r->coeffs[8*i+1] &= 0x1FFF; + + r->coeffs[8*i+2] = a[13*i+3] >> 2; + r->coeffs[8*i+2] |= (uint32_t)a[13*i+4] << 6; + r->coeffs[8*i+2] &= 0x1FFF; + + r->coeffs[8*i+3] = a[13*i+4] >> 7; + r->coeffs[8*i+3] |= (uint32_t)a[13*i+5] << 1; + r->coeffs[8*i+3] |= (uint32_t)a[13*i+6] << 9; + r->coeffs[8*i+3] &= 0x1FFF; + + r->coeffs[8*i+4] = a[13*i+6] >> 4; + r->coeffs[8*i+4] |= (uint32_t)a[13*i+7] << 4; + r->coeffs[8*i+4] |= (uint32_t)a[13*i+8] << 12; + r->coeffs[8*i+4] &= 0x1FFF; + + r->coeffs[8*i+5] = a[13*i+8] >> 1; + r->coeffs[8*i+5] |= (uint32_t)a[13*i+9] << 7; + r->coeffs[8*i+5] &= 0x1FFF; + + r->coeffs[8*i+6] = a[13*i+9] >> 6; + r->coeffs[8*i+6] |= (uint32_t)a[13*i+10] << 2; + r->coeffs[8*i+6] |= (uint32_t)a[13*i+11] << 10; + r->coeffs[8*i+6] &= 0x1FFF; + + r->coeffs[8*i+7] = a[13*i+11] >> 3; + r->coeffs[8*i+7] |= (uint32_t)a[13*i+12] << 5; + r->coeffs[8*i+7] &= 0x1FFF; + + r->coeffs[8*i+0] = (1 << (D-1)) - r->coeffs[8*i+0]; + r->coeffs[8*i+1] = (1 << (D-1)) - r->coeffs[8*i+1]; + r->coeffs[8*i+2] = (1 << (D-1)) - r->coeffs[8*i+2]; + r->coeffs[8*i+3] = (1 << (D-1)) - r->coeffs[8*i+3]; + r->coeffs[8*i+4] = (1 << (D-1)) - r->coeffs[8*i+4]; + r->coeffs[8*i+5] = (1 << (D-1)) - r->coeffs[8*i+5]; + r->coeffs[8*i+6] = (1 << (D-1)) - r->coeffs[8*i+6]; + r->coeffs[8*i+7] = (1 << (D-1)) - r->coeffs[8*i+7]; + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyz_pack +* +* Description: Bit-pack polynomial with coefficients +* in [-(GAMMA1 - 1), GAMMA1]. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYZ_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyz_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint32_t t[4]; + DBENCH_START(); + +#if GAMMA1 == (1 << 17) + for(i = 0; i < N/4; ++i) { + t[0] = GAMMA1 - a->coeffs[4*i+0]; + t[1] = GAMMA1 - a->coeffs[4*i+1]; + t[2] = GAMMA1 - a->coeffs[4*i+2]; + t[3] = GAMMA1 - a->coeffs[4*i+3]; + + r[9*i+0] = t[0]; + r[9*i+1] = t[0] >> 8; + r[9*i+2] = t[0] >> 16; + r[9*i+2] |= t[1] << 2; + r[9*i+3] = t[1] >> 6; + r[9*i+4] = t[1] >> 14; + r[9*i+4] |= t[2] << 4; + r[9*i+5] = t[2] >> 4; + r[9*i+6] = t[2] >> 12; + r[9*i+6] |= t[3] << 6; + r[9*i+7] = t[3] >> 2; + r[9*i+8] = t[3] >> 10; + } +#elif GAMMA1 == (1 << 19) + for(i = 0; i < N/2; ++i) { + t[0] = GAMMA1 - a->coeffs[2*i+0]; + t[1] = GAMMA1 - a->coeffs[2*i+1]; + + r[5*i+0] = t[0]; + r[5*i+1] = t[0] >> 8; + r[5*i+2] = t[0] >> 16; + r[5*i+2] |= t[1] << 4; + r[5*i+3] = t[1] >> 4; + r[5*i+4] = t[1] >> 12; + } +#endif + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyz_unpack +* +* Description: Unpack polynomial z with coefficients +* in [-(GAMMA1 - 1), GAMMA1]. +* +* Arguments: - poly *r: pointer to output polynomial +* - const uint8_t *a: byte array with bit-packed polynomial +**************************************************/ +void polyz_unpack(poly *r, const uint8_t *a) { + unsigned int i; + DBENCH_START(); + +#if GAMMA1 == (1 << 17) + for(i = 0; i < N/4; ++i) { + r->coeffs[4*i+0] = a[9*i+0]; + r->coeffs[4*i+0] |= (uint32_t)a[9*i+1] << 8; + r->coeffs[4*i+0] |= (uint32_t)a[9*i+2] << 16; + r->coeffs[4*i+0] &= 0x3FFFF; + + r->coeffs[4*i+1] = a[9*i+2] >> 2; + r->coeffs[4*i+1] |= (uint32_t)a[9*i+3] << 6; + r->coeffs[4*i+1] |= (uint32_t)a[9*i+4] << 14; + r->coeffs[4*i+1] &= 0x3FFFF; + + r->coeffs[4*i+2] = a[9*i+4] >> 4; + r->coeffs[4*i+2] |= (uint32_t)a[9*i+5] << 4; + r->coeffs[4*i+2] |= (uint32_t)a[9*i+6] << 12; + r->coeffs[4*i+2] &= 0x3FFFF; + + r->coeffs[4*i+3] = a[9*i+6] >> 6; + r->coeffs[4*i+3] |= (uint32_t)a[9*i+7] << 2; + r->coeffs[4*i+3] |= (uint32_t)a[9*i+8] << 10; + r->coeffs[4*i+3] &= 0x3FFFF; + + r->coeffs[4*i+0] = GAMMA1 - r->coeffs[4*i+0]; + r->coeffs[4*i+1] = GAMMA1 - r->coeffs[4*i+1]; + r->coeffs[4*i+2] = GAMMA1 - r->coeffs[4*i+2]; + r->coeffs[4*i+3] = GAMMA1 - r->coeffs[4*i+3]; + } +#elif GAMMA1 == (1 << 19) + for(i = 0; i < N/2; ++i) { + r->coeffs[2*i+0] = a[5*i+0]; + r->coeffs[2*i+0] |= (uint32_t)a[5*i+1] << 8; + r->coeffs[2*i+0] |= (uint32_t)a[5*i+2] << 16; + r->coeffs[2*i+0] &= 0xFFFFF; + + r->coeffs[2*i+1] = a[5*i+2] >> 4; + r->coeffs[2*i+1] |= (uint32_t)a[5*i+3] << 4; + r->coeffs[2*i+1] |= (uint32_t)a[5*i+4] << 12; + /* r->coeffs[2*i+1] &= 0xFFFFF; */ /* No effect, since we're anyway at 20 bits */ + + r->coeffs[2*i+0] = GAMMA1 - r->coeffs[2*i+0]; + r->coeffs[2*i+1] = GAMMA1 - r->coeffs[2*i+1]; + } +#endif + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyw1_pack +* +* Description: Bit-pack polynomial w1 with coefficients in [0,15] or [0,43]. +* Input coefficients are assumed to be standard representatives. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYW1_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyw1_pack(uint8_t *r, const poly *a) { + unsigned int i; + DBENCH_START(); + +#if GAMMA2 == (Q-1)/88 + for(i = 0; i < N/4; ++i) { + r[3*i+0] = a->coeffs[4*i+0]; + r[3*i+0] |= a->coeffs[4*i+1] << 6; + r[3*i+1] = a->coeffs[4*i+1] >> 2; + r[3*i+1] |= a->coeffs[4*i+2] << 4; + r[3*i+2] = a->coeffs[4*i+2] >> 4; + r[3*i+2] |= a->coeffs[4*i+3] << 2; + } +#elif GAMMA2 == (Q-1)/32 + for(i = 0; i < N/2; ++i) + r[i] = a->coeffs[2*i+0] | (a->coeffs[2*i+1] << 4); +#endif + + DBENCH_STOP(*tpack); +} diff --git a/ref/poly.h b/ref/poly.h new file mode 100644 index 0000000..904baa1 --- /dev/null +++ b/ref/poly.h @@ -0,0 +1,79 @@ +#ifndef POLY_H +#define POLY_H + +#include +#include "params.h" + +typedef struct { + int32_t coeffs[N]; +} poly; + +#define poly_reduce DILITHIUM_NAMESPACE(poly_reduce) +void poly_reduce(poly *a); +#define poly_caddq DILITHIUM_NAMESPACE(poly_caddq) +void poly_caddq(poly *a); + +#define poly_add DILITHIUM_NAMESPACE(poly_add) +void poly_add(poly *c, const poly *a, const poly *b); +#define poly_sub DILITHIUM_NAMESPACE(poly_sub) +void poly_sub(poly *c, const poly *a, const poly *b); +#define poly_shiftl DILITHIUM_NAMESPACE(poly_shiftl) +void poly_shiftl(poly *a); + +#define poly_ntt DILITHIUM_NAMESPACE(poly_ntt) +void poly_ntt(poly *a); +#define poly_invntt_tomont DILITHIUM_NAMESPACE(poly_invntt_tomont) +void poly_invntt_tomont(poly *a); +#define poly_pointwise_montgomery DILITHIUM_NAMESPACE(poly_pointwise_montgomery) +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); + +#define poly_power2round DILITHIUM_NAMESPACE(poly_power2round) +void poly_power2round(poly *a1, poly *a0, const poly *a); +#define poly_decompose DILITHIUM_NAMESPACE(poly_decompose) +void poly_decompose(poly *a1, poly *a0, const poly *a); +#define poly_make_hint DILITHIUM_NAMESPACE(poly_make_hint) +unsigned int poly_make_hint(poly *h, const poly *a0, const poly *a1); +#define poly_use_hint DILITHIUM_NAMESPACE(poly_use_hint) +void poly_use_hint(poly *b, const poly *a, const poly *h); + +#define poly_chknorm DILITHIUM_NAMESPACE(poly_chknorm) +int poly_chknorm(const poly *a, int32_t B); +#define poly_uniform DILITHIUM_NAMESPACE(poly_uniform) +void poly_uniform(poly *a, + const uint8_t seed[SEEDBYTES], + uint16_t nonce); +#define poly_uniform_eta DILITHIUM_NAMESPACE(poly_uniform_eta) +void poly_uniform_eta(poly *a, + const uint8_t seed[CRHBYTES], + uint16_t nonce); +#define poly_uniform_gamma1 DILITHIUM_NAMESPACE(poly_uniform_gamma1) +void poly_uniform_gamma1(poly *a, + const uint8_t seed[CRHBYTES], + uint16_t nonce); +#define poly_challenge DILITHIUM_NAMESPACE(poly_challenge) +void poly_challenge(poly *c, const uint8_t seed[CTILDEBYTES]); + +#define polyeta_pack DILITHIUM_NAMESPACE(polyeta_pack) +void polyeta_pack(uint8_t *r, const poly *a); +#define polyeta_unpack DILITHIUM_NAMESPACE(polyeta_unpack) +void polyeta_unpack(poly *r, const uint8_t *a); + +#define polyt1_pack DILITHIUM_NAMESPACE(polyt1_pack) +void polyt1_pack(uint8_t *r, const poly *a); +#define polyt1_unpack DILITHIUM_NAMESPACE(polyt1_unpack) +void polyt1_unpack(poly *r, const uint8_t *a); + +#define polyt0_pack DILITHIUM_NAMESPACE(polyt0_pack) +void polyt0_pack(uint8_t *r, const poly *a); +#define polyt0_unpack DILITHIUM_NAMESPACE(polyt0_unpack) +void polyt0_unpack(poly *r, const uint8_t *a); + +#define polyz_pack DILITHIUM_NAMESPACE(polyz_pack) +void polyz_pack(uint8_t *r, const poly *a); +#define polyz_unpack DILITHIUM_NAMESPACE(polyz_unpack) +void polyz_unpack(poly *r, const uint8_t *a); + +#define polyw1_pack DILITHIUM_NAMESPACE(polyw1_pack) +void polyw1_pack(uint8_t *r, const poly *a); + +#endif diff --git a/ref/polyvec.c b/ref/polyvec.c new file mode 100644 index 0000000..241f618 --- /dev/null +++ b/ref/polyvec.c @@ -0,0 +1,389 @@ +#include +#include "params.h" +#include "polyvec.h" +#include "poly.h" + +/************************************************* +* Name: expand_mat +* +* Description: Implementation of ExpandA. Generates matrix A with uniformly +* random coefficients a_{i,j} by performing rejection +* sampling on the output stream of SHAKE128(rho|j|i) +* +* Arguments: - polyvecl mat[K]: output matrix +* - const uint8_t rho[]: byte array containing seed rho +**************************************************/ +void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { + unsigned int i, j; + + for(i = 0; i < K; ++i) + for(j = 0; j < L; ++j) + poly_uniform(&mat[i].vec[j], rho, (i << 8) + j); +} + +void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); +} + +/**************************************************************/ +/************ Vectors of polynomials of length L **************/ +/**************************************************************/ + +void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_uniform_eta(&v->vec[i], seed, nonce++); +} + +void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_uniform_gamma1(&v->vec[i], seed, L*nonce + i); +} + +void polyvecl_reduce(polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_reduce(&v->vec[i]); +} + +/************************************************* +* Name: polyvecl_add +* +* Description: Add vectors of polynomials of length L. +* No modular reduction is performed. +* +* Arguments: - polyvecl *w: pointer to output vector +* - const polyvecl *u: pointer to first summand +* - const polyvecl *v: pointer to second summand +**************************************************/ +void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyvecl_ntt +* +* Description: Forward NTT of all polynomials in vector of length L. Output +* coefficients can be up to 16*Q larger than input coefficients. +* +* Arguments: - polyvecl *v: pointer to input/output vector +**************************************************/ +void polyvecl_ntt(polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_ntt(&v->vec[i]); +} + +void polyvecl_invntt_tomont(polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_invntt_tomont(&v->vec[i]); +} + +void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); +} + +/************************************************* +* Name: polyvecl_pointwise_acc_montgomery +* +* Description: Pointwise multiply vectors of polynomials of length L, multiply +* resulting vector by 2^{-32} and add (accumulate) polynomials +* in it. Input/output vectors are in NTT domain representation. +* +* Arguments: - poly *w: output polynomial +* - const polyvecl *u: pointer to first input vector +* - const polyvecl *v: pointer to second input vector +**************************************************/ +void polyvecl_pointwise_acc_montgomery(poly *w, + const polyvecl *u, + const polyvecl *v) +{ + unsigned int i; + poly t; + + poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); + for(i = 1; i < L; ++i) { + poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); + poly_add(w, w, &t); + } +} + +/************************************************* +* Name: polyvecl_chknorm +* +* Description: Check infinity norm of polynomials in vector of length L. +* Assumes input polyvecl to be reduced by polyvecl_reduce(). +* +* Arguments: - const polyvecl *v: pointer to vector +* - int32_t B: norm bound +* +* Returns 0 if norm of all polynomials is strictly smaller than B <= (Q-1)/8 +* and 1 otherwise. +**************************************************/ +int polyvecl_chknorm(const polyvecl *v, int32_t bound) { + unsigned int i; + + for(i = 0; i < L; ++i) + if(poly_chknorm(&v->vec[i], bound)) + return 1; + + return 0; +} + +/**************************************************************/ +/************ Vectors of polynomials of length K **************/ +/**************************************************************/ + +void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_uniform_eta(&v->vec[i], seed, nonce++); +} + +/************************************************* +* Name: polyveck_reduce +* +* Description: Reduce coefficients of polynomials in vector of length K +* to representatives in [-6283008,6283008]. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_reduce(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_reduce(&v->vec[i]); +} + +/************************************************* +* Name: polyveck_caddq +* +* Description: For all coefficients of polynomials in vector of length K +* add Q if coefficient is negative. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_caddq(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_caddq(&v->vec[i]); +} + +/************************************************* +* Name: polyveck_add +* +* Description: Add vectors of polynomials of length K. +* No modular reduction is performed. +* +* Arguments: - polyveck *w: pointer to output vector +* - const polyveck *u: pointer to first summand +* - const polyveck *v: pointer to second summand +**************************************************/ +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_sub +* +* Description: Subtract vectors of polynomials of length K. +* No modular reduction is performed. +* +* Arguments: - polyveck *w: pointer to output vector +* - const polyveck *u: pointer to first input vector +* - const polyveck *v: pointer to second input vector to be +* subtracted from first input vector +**************************************************/ +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_shiftl +* +* Description: Multiply vector of polynomials of Length K by 2^D without modular +* reduction. Assumes input coefficients to be less than 2^{31-D}. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_shiftl(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_shiftl(&v->vec[i]); +} + +/************************************************* +* Name: polyveck_ntt +* +* Description: Forward NTT of all polynomials in vector of length K. Output +* coefficients can be up to 16*Q larger than input coefficients. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_ntt(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_ntt(&v->vec[i]); +} + +/************************************************* +* Name: polyveck_invntt_tomont +* +* Description: Inverse NTT and multiplication by 2^{32} of polynomials +* in vector of length K. Input coefficients need to be less +* than 2*Q. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_invntt_tomont(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_invntt_tomont(&v->vec[i]); +} + +void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); +} + + +/************************************************* +* Name: polyveck_chknorm +* +* Description: Check infinity norm of polynomials in vector of length K. +* Assumes input polyveck to be reduced by polyveck_reduce(). +* +* Arguments: - const polyveck *v: pointer to vector +* - int32_t B: norm bound +* +* Returns 0 if norm of all polynomials are strictly smaller than B <= (Q-1)/8 +* and 1 otherwise. +**************************************************/ +int polyveck_chknorm(const polyveck *v, int32_t bound) { + unsigned int i; + + for(i = 0; i < K; ++i) + if(poly_chknorm(&v->vec[i], bound)) + return 1; + + return 0; +} + +/************************************************* +* Name: polyveck_power2round +* +* Description: For all coefficients a of polynomials in vector of length K, +* compute a0, a1 such that a mod^+ Q = a1*2^D + a0 +* with -2^{D-1} < a0 <= 2^{D-1}. Assumes coefficients to be +* standard representatives. +* +* Arguments: - polyveck *v1: pointer to output vector of polynomials with +* coefficients a1 +* - polyveck *v0: pointer to output vector of polynomials with +* coefficients a0 +* - const polyveck *v: pointer to input vector +**************************************************/ +void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_power2round(&v1->vec[i], &v0->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_decompose +* +* Description: For all coefficients a of polynomials in vector of length K, +* compute high and low bits a0, a1 such a mod^+ Q = a1*ALPHA + a0 +* with -ALPHA/2 < a0 <= ALPHA/2 except a1 = (Q-1)/ALPHA where we +* set a1 = 0 and -ALPHA/2 <= a0 = a mod Q - Q < 0. +* Assumes coefficients to be standard representatives. +* +* Arguments: - polyveck *v1: pointer to output vector of polynomials with +* coefficients a1 +* - polyveck *v0: pointer to output vector of polynomials with +* coefficients a0 +* - const polyveck *v: pointer to input vector +**************************************************/ +void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_decompose(&v1->vec[i], &v0->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_make_hint +* +* Description: Compute hint vector. +* +* Arguments: - polyveck *h: pointer to output vector +* - const polyveck *v0: pointer to low part of input vector +* - const polyveck *v1: pointer to high part of input vector +* +* Returns number of 1 bits. +**************************************************/ +unsigned int polyveck_make_hint(polyveck *h, + const polyveck *v0, + const polyveck *v1) +{ + unsigned int i, s = 0; + + for(i = 0; i < K; ++i) + s += poly_make_hint(&h->vec[i], &v0->vec[i], &v1->vec[i]); + + return s; +} + +/************************************************* +* Name: polyveck_use_hint +* +* Description: Use hint vector to correct the high bits of input vector. +* +* Arguments: - polyveck *w: pointer to output vector of polynomials with +* corrected high bits +* - const polyveck *u: pointer to input vector +* - const polyveck *h: pointer to input hint vector +**************************************************/ +void polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_use_hint(&w->vec[i], &u->vec[i], &h->vec[i]); +} + +void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1) { + unsigned int i; + + for(i = 0; i < K; ++i) + polyw1_pack(&r[i*POLYW1_PACKEDBYTES], &w1->vec[i]); +} diff --git a/ref/polyvec.h b/ref/polyvec.h new file mode 100644 index 0000000..615ac52 --- /dev/null +++ b/ref/polyvec.h @@ -0,0 +1,93 @@ +#ifndef POLYVEC_H +#define POLYVEC_H + +#include +#include "params.h" +#include "poly.h" + +/* Vectors of polynomials of length L */ +typedef struct { + poly vec[L]; +} polyvecl; + +#define polyvecl_uniform_eta DILITHIUM_NAMESPACE(polyvecl_uniform_eta) +void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyvecl_uniform_gamma1 DILITHIUM_NAMESPACE(polyvecl_uniform_gamma1) +void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyvecl_reduce DILITHIUM_NAMESPACE(polyvecl_reduce) +void polyvecl_reduce(polyvecl *v); + +#define polyvecl_add DILITHIUM_NAMESPACE(polyvecl_add) +void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v); + +#define polyvecl_ntt DILITHIUM_NAMESPACE(polyvecl_ntt) +void polyvecl_ntt(polyvecl *v); +#define polyvecl_invntt_tomont DILITHIUM_NAMESPACE(polyvecl_invntt_tomont) +void polyvecl_invntt_tomont(polyvecl *v); +#define polyvecl_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyvecl_pointwise_poly_montgomery) +void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v); +#define polyvecl_pointwise_acc_montgomery \ + DILITHIUM_NAMESPACE(polyvecl_pointwise_acc_montgomery) +void polyvecl_pointwise_acc_montgomery(poly *w, + const polyvecl *u, + const polyvecl *v); + + +#define polyvecl_chknorm DILITHIUM_NAMESPACE(polyvecl_chknorm) +int polyvecl_chknorm(const polyvecl *v, int32_t B); + + + +/* Vectors of polynomials of length K */ +typedef struct { + poly vec[K]; +} polyveck; + +#define polyveck_uniform_eta DILITHIUM_NAMESPACE(polyveck_uniform_eta) +void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyveck_reduce DILITHIUM_NAMESPACE(polyveck_reduce) +void polyveck_reduce(polyveck *v); +#define polyveck_caddq DILITHIUM_NAMESPACE(polyveck_caddq) +void polyveck_caddq(polyveck *v); + +#define polyveck_add DILITHIUM_NAMESPACE(polyveck_add) +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_sub DILITHIUM_NAMESPACE(polyveck_sub) +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_shiftl DILITHIUM_NAMESPACE(polyveck_shiftl) +void polyveck_shiftl(polyveck *v); + +#define polyveck_ntt DILITHIUM_NAMESPACE(polyveck_ntt) +void polyveck_ntt(polyveck *v); +#define polyveck_invntt_tomont DILITHIUM_NAMESPACE(polyveck_invntt_tomont) +void polyveck_invntt_tomont(polyveck *v); +#define polyveck_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyveck_pointwise_poly_montgomery) +void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v); + +#define polyveck_chknorm DILITHIUM_NAMESPACE(polyveck_chknorm) +int polyveck_chknorm(const polyveck *v, int32_t B); + +#define polyveck_power2round DILITHIUM_NAMESPACE(polyveck_power2round) +void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v); +#define polyveck_decompose DILITHIUM_NAMESPACE(polyveck_decompose) +void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v); +#define polyveck_make_hint DILITHIUM_NAMESPACE(polyveck_make_hint) +unsigned int polyveck_make_hint(polyveck *h, + const polyveck *v0, + const polyveck *v1); +#define polyveck_use_hint DILITHIUM_NAMESPACE(polyveck_use_hint) +void polyveck_use_hint(polyveck *w, const polyveck *v, const polyveck *h); + +#define polyveck_pack_w1 DILITHIUM_NAMESPACE(polyveck_pack_w1) +void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1); + +#define polyvec_matrix_expand DILITHIUM_NAMESPACE(polyvec_matrix_expand) +void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); + +#define polyvec_matrix_pointwise_montgomery DILITHIUM_NAMESPACE(polyvec_matrix_pointwise_montgomery) +void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v); + +#endif diff --git a/ref/precomp.gp b/ref/precomp.gp new file mode 100644 index 0000000..74dbdf8 --- /dev/null +++ b/ref/precomp.gp @@ -0,0 +1,12 @@ +precomp() = { + brv = [128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255]; + + q = 2^23 - 2^13 + 1; + qinv = Mod(1/q,2^32); + mont = Mod(2^32,q); + + z = 0; + for(i = 1, q-1, z = Mod(i,q); if(znorder(z) == 512, break)); + zetas = vector(255, i, centerlift(mont * z^(brv[i]))); + return(zetas); +} diff --git a/ref/randombytes.c b/ref/randombytes.c new file mode 100644 index 0000000..7f4b857 --- /dev/null +++ b/ref/randombytes.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include "randombytes.h" + +#ifdef _WIN32 +#include +#include +#else +#include +#include +#ifdef __linux__ +#define _GNU_SOURCE +#include +#include +#else +#include +#endif +#endif + +#ifdef _WIN32 +void randombytes(uint8_t *out, size_t outlen) { + HCRYPTPROV ctx; + size_t len; + + if(!CryptAcquireContext(&ctx, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) + abort(); + + while(outlen > 0) { + len = (outlen > 1048576) ? 1048576 : outlen; + if(!CryptGenRandom(ctx, len, (BYTE *)out)) + abort(); + + out += len; + outlen -= len; + } + + if(!CryptReleaseContext(ctx, 0)) + abort(); +} +#elif defined(__linux__) && defined(SYS_getrandom) +void randombytes(uint8_t *out, size_t outlen) { + ssize_t ret; + + while(outlen > 0) { + ret = syscall(SYS_getrandom, out, outlen, 0); + if(ret == -1 && errno == EINTR) + continue; + else if(ret == -1) + abort(); + + out += ret; + outlen -= ret; + } +} +#else +void randombytes(uint8_t *out, size_t outlen) { + static int fd = -1; + ssize_t ret; + + while(fd == -1) { + fd = open("/dev/urandom", O_RDONLY); + if(fd == -1 && errno == EINTR) + continue; + else if(fd == -1) + abort(); + } + + while(outlen > 0) { + ret = read(fd, out, outlen); + if(ret == -1 && errno == EINTR) + continue; + else if(ret == -1) + abort(); + + out += ret; + outlen -= ret; + } +} +#endif diff --git a/ref/randombytes.h b/ref/randombytes.h new file mode 100644 index 0000000..619b7f9 --- /dev/null +++ b/ref/randombytes.h @@ -0,0 +1,9 @@ +#ifndef RANDOMBYTES_H +#define RANDOMBYTES_H + +#include +#include + +void randombytes(uint8_t *out, size_t outlen); + +#endif diff --git a/ref/reduce.c b/ref/reduce.c new file mode 100644 index 0000000..8479a22 --- /dev/null +++ b/ref/reduce.c @@ -0,0 +1,69 @@ +#include +#include "params.h" +#include "reduce.h" + +/************************************************* +* Name: montgomery_reduce +* +* Description: For finite field element a with -2^{31}Q <= a <= Q*2^31, +* compute r \equiv a*2^{-32} (mod Q) such that -Q < r < Q. +* +* Arguments: - int64_t: finite field element a +* +* Returns r. +**************************************************/ +int32_t montgomery_reduce(int64_t a) { + int32_t t; + + t = (int64_t)(int32_t)a*QINV; + t = (a - (int64_t)t*Q) >> 32; + return t; +} + +/************************************************* +* Name: reduce32 +* +* Description: For finite field element a with a <= 2^{31} - 2^{22} - 1, +* compute r \equiv a (mod Q) such that -6283008 <= r <= 6283008. +* +* Arguments: - int32_t: finite field element a +* +* Returns r. +**************************************************/ +int32_t reduce32(int32_t a) { + int32_t t; + + t = (a + (1 << 22)) >> 23; + t = a - t*Q; + return t; +} + +/************************************************* +* Name: caddq +* +* Description: Add Q if input coefficient is negative. +* +* Arguments: - int32_t: finite field element a +* +* Returns r. +**************************************************/ +int32_t caddq(int32_t a) { + a += (a >> 31) & Q; + return a; +} + +/************************************************* +* Name: freeze +* +* Description: For finite field element a, compute standard +* representative r = a mod^+ Q. +* +* Arguments: - int32_t: finite field element a +* +* Returns r. +**************************************************/ +int32_t freeze(int32_t a) { + a = reduce32(a); + a = caddq(a); + return a; +} diff --git a/ref/reduce.h b/ref/reduce.h new file mode 100644 index 0000000..26d9b4e --- /dev/null +++ b/ref/reduce.h @@ -0,0 +1,22 @@ +#ifndef REDUCE_H +#define REDUCE_H + +#include +#include "params.h" + +#define MONT -4186625 // 2^32 % Q +#define QINV 58728449 // q^(-1) mod 2^32 + +#define montgomery_reduce DILITHIUM_NAMESPACE(montgomery_reduce) +int32_t montgomery_reduce(int64_t a); + +#define reduce32 DILITHIUM_NAMESPACE(reduce32) +int32_t reduce32(int32_t a); + +#define caddq DILITHIUM_NAMESPACE(caddq) +int32_t caddq(int32_t a); + +#define freeze DILITHIUM_NAMESPACE(freeze) +int32_t freeze(int32_t a); + +#endif diff --git a/ref/rounding.c b/ref/rounding.c new file mode 100644 index 0000000..889f0a2 --- /dev/null +++ b/ref/rounding.c @@ -0,0 +1,102 @@ +#include +#include "params.h" +#include "rounding.h" + +/************************************************* +* Name: power2round +* +* Description: For finite field element a, compute a0, a1 such that +* a mod^+ Q = a1*2^D + a0 with -2^{D-1} < a0 <= 2^{D-1}. +* Assumes a to be standard representative. +* +* Arguments: - int32_t a: input element +* - int32_t *a0: pointer to output element a0 +* +* Returns a1. +**************************************************/ +int32_t power2round(int32_t *a0, int32_t a) { + int32_t a1; + + a1 = (a + (1 << (D-1)) - 1) >> D; + *a0 = a - (a1 << D); + return a1; +} + +/************************************************* +* Name: decompose +* +* Description: For finite field element a, compute high and low bits a0, a1 such +* that a mod^+ Q = a1*ALPHA + a0 with -ALPHA/2 < a0 <= ALPHA/2 except +* if a1 = (Q-1)/ALPHA where we set a1 = 0 and +* -ALPHA/2 <= a0 = a mod^+ Q - Q < 0. Assumes a to be standard +* representative. +* +* Arguments: - int32_t a: input element +* - int32_t *a0: pointer to output element a0 +* +* Returns a1. +**************************************************/ +int32_t decompose(int32_t *a0, int32_t a) { + int32_t a1; + + a1 = (a + 127) >> 7; +#if GAMMA2 == (Q-1)/32 + a1 = (a1*1025 + (1 << 21)) >> 22; + a1 &= 15; +#elif GAMMA2 == (Q-1)/88 + a1 = (a1*11275 + (1 << 23)) >> 24; + a1 ^= ((43 - a1) >> 31) & a1; +#endif + + *a0 = a - a1*2*GAMMA2; + *a0 -= (((Q-1)/2 - *a0) >> 31) & Q; + return a1; +} + +/************************************************* +* Name: make_hint +* +* Description: Compute hint bit indicating whether the low bits of the +* input element overflow into the high bits. +* +* Arguments: - int32_t a0: low bits of input element +* - int32_t a1: high bits of input element +* +* Returns 1 if overflow. +**************************************************/ +unsigned int make_hint(int32_t a0, int32_t a1) { + if(a0 > GAMMA2 || a0 < -GAMMA2 || (a0 == -GAMMA2 && a1 != 0)) + return 1; + + return 0; +} + +/************************************************* +* Name: use_hint +* +* Description: Correct high bits according to hint. +* +* Arguments: - int32_t a: input element +* - unsigned int hint: hint bit +* +* Returns corrected high bits. +**************************************************/ +int32_t use_hint(int32_t a, unsigned int hint) { + int32_t a0, a1; + + a1 = decompose(&a0, a); + if(hint == 0) + return a1; + +#if GAMMA2 == (Q-1)/32 + if(a0 > 0) + return (a1 + 1) & 15; + else + return (a1 - 1) & 15; +#elif GAMMA2 == (Q-1)/88 + if(a0 > 0) + return (a1 == 43) ? 0 : a1 + 1; + else + return (a1 == 0) ? 43 : a1 - 1; +#endif +} diff --git a/ref/rounding.h b/ref/rounding.h new file mode 100644 index 0000000..b72e8e8 --- /dev/null +++ b/ref/rounding.h @@ -0,0 +1,19 @@ +#ifndef ROUNDING_H +#define ROUNDING_H + +#include +#include "params.h" + +#define power2round DILITHIUM_NAMESPACE(power2round) +int32_t power2round(int32_t *a0, int32_t a); + +#define decompose DILITHIUM_NAMESPACE(decompose) +int32_t decompose(int32_t *a0, int32_t a); + +#define make_hint DILITHIUM_NAMESPACE(make_hint) +unsigned int make_hint(int32_t a0, int32_t a1); + +#define use_hint DILITHIUM_NAMESPACE(use_hint) +int32_t use_hint(int32_t a, unsigned int hint); + +#endif diff --git a/ref/sign.c b/ref/sign.c new file mode 100644 index 0000000..7d3f882 --- /dev/null +++ b/ref/sign.c @@ -0,0 +1,443 @@ +#include +#include "params.h" +#include "sign.h" +#include "packing.h" +#include "polyvec.h" +#include "poly.h" +#include "randombytes.h" +#include "symmetric.h" +#include "fips202.h" + +/************************************************* +* Name: crypto_sign_keypair +* +* Description: Generates public and private key. +* +* Arguments: - uint8_t *pk: pointer to output public key (allocated +* array of CRYPTO_PUBLICKEYBYTES bytes) +* - uint8_t *sk: pointer to output private key (allocated +* array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seedbuf[2*SEEDBYTES + CRHBYTES]; + uint8_t tr[TRBYTES]; + const uint8_t *rho, *rhoprime, *key; + polyvecl mat[K]; + polyvecl s1, s1hat; + polyveck s2, t1, t0; + + /* Get randomness for rho, rhoprime and key */ + randombytes(seedbuf, SEEDBYTES); + seedbuf[SEEDBYTES+0] = K; + seedbuf[SEEDBYTES+1] = L; + shake256(seedbuf, 2*SEEDBYTES + CRHBYTES, seedbuf, SEEDBYTES+2); + rho = seedbuf; + rhoprime = rho + SEEDBYTES; + key = rhoprime + CRHBYTES; + + /* Expand matrix */ + polyvec_matrix_expand(mat, rho); + + /* Sample short vectors s1 and s2 */ + polyvecl_uniform_eta(&s1, rhoprime, 0); + polyveck_uniform_eta(&s2, rhoprime, L); + + /* Matrix-vector multiplication */ + s1hat = s1; + polyvecl_ntt(&s1hat); + polyvec_matrix_pointwise_montgomery(&t1, mat, &s1hat); + polyveck_reduce(&t1); + polyveck_invntt_tomont(&t1); + + /* Add error vector s2 */ + polyveck_add(&t1, &t1, &s2); + + /* Extract t1 and write public key */ + polyveck_caddq(&t1); + polyveck_power2round(&t1, &t0, &t1); + pack_pk(pk, rho, &t1); + + /* Compute H(rho, t1) and write secret key */ + shake256(tr, TRBYTES, pk, CRYPTO_PUBLICKEYBYTES); + pack_sk(sk, rho, tr, key, &t0, &s1, &s2); + + return 0; +} + +/************************************************* +* Name: crypto_sign_signature_internal +* +* Description: Computes signature. Internal API. +* +* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES) +* - size_t *siglen: pointer to output length of signature +* - uint8_t *m: pointer to message to be signed +* - size_t mlen: length of message +* - uint8_t *pre: pointer to prefix string +* - size_t prelen: length of prefix string +* - uint8_t *rnd: pointer to random seed +* - uint8_t *sk: pointer to bit-packed secret key +* +* Returns 0 (success) +**************************************************/ +int crypto_sign_signature_internal(uint8_t *sig, + size_t *siglen, + const uint8_t *m, + size_t mlen, + const uint8_t *pre, + size_t prelen, + const uint8_t rnd[RNDBYTES], + const uint8_t *sk) +{ + unsigned int n; + uint8_t seedbuf[2*SEEDBYTES + TRBYTES + 2*CRHBYTES]; + uint8_t *rho, *tr, *key, *mu, *rhoprime; + uint16_t nonce = 0; + polyvecl mat[K], s1, y, z; + polyveck t0, s2, w1, w0, h; + poly cp; + keccak_state state; + + rho = seedbuf; + tr = rho + SEEDBYTES; + key = tr + TRBYTES; + mu = key + SEEDBYTES; + rhoprime = mu + CRHBYTES; + unpack_sk(rho, tr, key, &t0, &s1, &s2, sk); + + /* Compute mu = CRH(tr, pre, msg) */ + shake256_init(&state); + shake256_absorb(&state, tr, TRBYTES); + shake256_absorb(&state, pre, prelen); + shake256_absorb(&state, m, mlen); + shake256_finalize(&state); + shake256_squeeze(mu, CRHBYTES, &state); + + /* Compute rhoprime = CRH(key, rnd, mu) */ + shake256_init(&state); + shake256_absorb(&state, key, SEEDBYTES); + shake256_absorb(&state, rnd, RNDBYTES); + shake256_absorb(&state, mu, CRHBYTES); + shake256_finalize(&state); + shake256_squeeze(rhoprime, CRHBYTES, &state); + + /* Expand matrix and transform vectors */ + polyvec_matrix_expand(mat, rho); + polyvecl_ntt(&s1); + polyveck_ntt(&s2); + polyveck_ntt(&t0); + +rej: + /* Sample intermediate vector y */ + polyvecl_uniform_gamma1(&y, rhoprime, nonce++); + + /* Matrix-vector multiplication */ + z = y; + polyvecl_ntt(&z); + polyvec_matrix_pointwise_montgomery(&w1, mat, &z); + polyveck_reduce(&w1); + polyveck_invntt_tomont(&w1); + + /* Decompose w and call the random oracle */ + polyveck_caddq(&w1); + polyveck_decompose(&w1, &w0, &w1); + polyveck_pack_w1(sig, &w1); + + shake256_init(&state); + shake256_absorb(&state, mu, CRHBYTES); + shake256_absorb(&state, sig, K*POLYW1_PACKEDBYTES); + shake256_finalize(&state); + shake256_squeeze(sig, CTILDEBYTES, &state); + poly_challenge(&cp, sig); + poly_ntt(&cp); + + /* Compute z, reject if it reveals secret */ + polyvecl_pointwise_poly_montgomery(&z, &cp, &s1); + polyvecl_invntt_tomont(&z); + polyvecl_add(&z, &z, &y); + polyvecl_reduce(&z); + if(polyvecl_chknorm(&z, GAMMA1 - BETA)) + goto rej; + + /* Check that subtracting cs2 does not change high bits of w and low bits + * do not reveal secret information */ + polyveck_pointwise_poly_montgomery(&h, &cp, &s2); + polyveck_invntt_tomont(&h); + polyveck_sub(&w0, &w0, &h); + polyveck_reduce(&w0); + if(polyveck_chknorm(&w0, GAMMA2 - BETA)) + goto rej; + + /* Compute hints for w1 */ + polyveck_pointwise_poly_montgomery(&h, &cp, &t0); + polyveck_invntt_tomont(&h); + polyveck_reduce(&h); + if(polyveck_chknorm(&h, GAMMA2)) + goto rej; + + polyveck_add(&w0, &w0, &h); + n = polyveck_make_hint(&h, &w0, &w1); + if(n > OMEGA) + goto rej; + + /* Write signature */ + pack_sig(sig, sig, &z, &h); + *siglen = CRYPTO_BYTES; + return 0; +} + +/************************************************* +* Name: crypto_sign_signature +* +* Description: Computes signature. +* +* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES) +* - size_t *siglen: pointer to output length of signature +* - uint8_t *m: pointer to message to be signed +* - size_t mlen: length of message +* - uint8_t *ctx: pointer to contex string +* - size_t ctxlen: length of contex string +* - uint8_t *sk: pointer to bit-packed secret key +* +* Returns 0 (success) or -1 (context string too long) +**************************************************/ +int crypto_sign_signature(uint8_t *sig, + size_t *siglen, + const uint8_t *m, + size_t mlen, + const uint8_t *ctx, + size_t ctxlen, + const uint8_t *sk) +{ + size_t i; + uint8_t pre[257]; + uint8_t rnd[RNDBYTES]; + + if(ctxlen > 255) + return -1; + + /* Prepare pre = (0, ctxlen, ctx) */ + pre[0] = 0; + pre[1] = ctxlen; + for(i = 0; i < ctxlen; i++) + pre[2 + i] = ctx[i]; + +#ifdef DILITHIUM_RANDOMIZED_SIGNING + randombytes(rnd, RNDBYTES); +#else + for(i=0;i 255) + return -1; + + pre[0] = 0; + pre[1] = ctxlen; + for(i = 0; i < ctxlen; i++) + pre[2 + i] = ctx[i]; + + return crypto_sign_verify_internal(sig,siglen,m,mlen,pre,2+ctxlen,pk); +} + +/************************************************* +* Name: crypto_sign_open +* +* Description: Verify signed message. +* +* Arguments: - uint8_t *m: pointer to output message (allocated +* array with smlen bytes), can be equal to sm +* - size_t *mlen: pointer to output length of message +* - const uint8_t *sm: pointer to signed message +* - size_t smlen: length of signed message +* - const uint8_t *ctx: pointer to context tring +* - size_t ctxlen: length of context string +* - const uint8_t *pk: pointer to bit-packed public key +* +* Returns 0 if signed message could be verified correctly and -1 otherwise +**************************************************/ +int crypto_sign_open(uint8_t *m, + size_t *mlen, + const uint8_t *sm, + size_t smlen, + const uint8_t *ctx, + size_t ctxlen, + const uint8_t *pk) +{ + size_t i; + + if(smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + if(crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, ctx, ctxlen, pk)) + goto badsig; + else { + /* All good, copy msg, return 0 */ + for(i = 0; i < *mlen; ++i) + m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = 0; + for(i = 0; i < smlen; ++i) + m[i] = 0; + + return -1; +} diff --git a/ref/sign.h b/ref/sign.h new file mode 100644 index 0000000..2741e8f --- /dev/null +++ b/ref/sign.h @@ -0,0 +1,56 @@ +#ifndef SIGN_H +#define SIGN_H + +#include +#include +#include "params.h" +#include "polyvec.h" +#include "poly.h" + +#define crypto_sign_keypair DILITHIUM_NAMESPACE(keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +#define crypto_sign_signature_internal DILITHIUM_NAMESPACE(signature_internal) +int crypto_sign_signature_internal(uint8_t *sig, + size_t *siglen, + const uint8_t *m, + size_t mlen, + const uint8_t *pre, + size_t prelen, + const uint8_t rnd[RNDBYTES], + const uint8_t *sk); + +#define crypto_sign_signature DILITHIUM_NAMESPACE(signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +#define crypto_sign DILITHIUM_NAMESPACETOP +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +#define crypto_sign_verify_internal DILITHIUM_NAMESPACE(verify_internal) +int crypto_sign_verify_internal(const uint8_t *sig, + size_t siglen, + const uint8_t *m, + size_t mlen, + const uint8_t *pre, + size_t prelen, + const uint8_t *pk); + +#define crypto_sign_verify DILITHIUM_NAMESPACE(verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +#define crypto_sign_open DILITHIUM_NAMESPACE(open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +#endif diff --git a/ref/symmetric-shake.c b/ref/symmetric-shake.c new file mode 100644 index 0000000..11ec09c --- /dev/null +++ b/ref/symmetric-shake.c @@ -0,0 +1,28 @@ +#include +#include "params.h" +#include "symmetric.h" +#include "fips202.h" + +void dilithium_shake128_stream_init(keccak_state *state, const uint8_t seed[SEEDBYTES], uint16_t nonce) +{ + uint8_t t[2]; + t[0] = nonce; + t[1] = nonce >> 8; + + shake128_init(state); + shake128_absorb(state, seed, SEEDBYTES); + shake128_absorb(state, t, 2); + shake128_finalize(state); +} + +void dilithium_shake256_stream_init(keccak_state *state, const uint8_t seed[CRHBYTES], uint16_t nonce) +{ + uint8_t t[2]; + t[0] = nonce; + t[1] = nonce >> 8; + + shake256_init(state); + shake256_absorb(state, seed, CRHBYTES); + shake256_absorb(state, t, 2); + shake256_finalize(state); +} diff --git a/ref/symmetric.h b/ref/symmetric.h new file mode 100644 index 0000000..cba12d1 --- /dev/null +++ b/ref/symmetric.h @@ -0,0 +1,34 @@ +#ifndef SYMMETRIC_H +#define SYMMETRIC_H + +#include +#include "params.h" + +#include "fips202.h" + +typedef keccak_state stream128_state; +typedef keccak_state stream256_state; + +#define dilithium_shake128_stream_init DILITHIUM_NAMESPACE(dilithium_shake128_stream_init) +void dilithium_shake128_stream_init(keccak_state *state, + const uint8_t seed[SEEDBYTES], + uint16_t nonce); + +#define dilithium_shake256_stream_init DILITHIUM_NAMESPACE(dilithium_shake256_stream_init) +void dilithium_shake256_stream_init(keccak_state *state, + const uint8_t seed[CRHBYTES], + uint16_t nonce); + +#define STREAM128_BLOCKBYTES SHAKE128_RATE +#define STREAM256_BLOCKBYTES SHAKE256_RATE + +#define stream128_init(STATE, SEED, NONCE) \ + dilithium_shake128_stream_init(STATE, SEED, NONCE) +#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + shake128_squeezeblocks(OUT, OUTBLOCKS, STATE) +#define stream256_init(STATE, SEED, NONCE) \ + dilithium_shake256_stream_init(STATE, SEED, NONCE) +#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) + +#endif diff --git a/ref/test/.gitignore b/ref/test/.gitignore new file mode 100644 index 0000000..99b3f73 --- /dev/null +++ b/ref/test/.gitignore @@ -0,0 +1,10 @@ +test_dilithium2 +test_dilithium3 +test_dilithium5 +test_vectors2 +test_vectors3 +test_vectors5 +test_speed2 +test_speed3 +test_speed5 +test_mul diff --git a/ref/test/cpucycles.c b/ref/test/cpucycles.c new file mode 100644 index 0000000..ccbf54d --- /dev/null +++ b/ref/test/cpucycles.c @@ -0,0 +1,17 @@ +#include +#include "cpucycles.h" + +uint64_t cpucycles_overhead(void) { + uint64_t t0, t1, overhead = -1LL; + unsigned int i; + + for(i=0;i<100000;i++) { + t0 = cpucycles(); + __asm__ volatile(""); + t1 = cpucycles(); + if(t1 - t0 < overhead) + overhead = t1 - t0; + } + + return overhead; +} diff --git a/ref/test/cpucycles.h b/ref/test/cpucycles.h new file mode 100644 index 0000000..7b7b9f7 --- /dev/null +++ b/ref/test/cpucycles.h @@ -0,0 +1,33 @@ +#ifndef CPUCYCLES_H +#define CPUCYCLES_H + +#include + +#ifdef USE_RDPMC /* Needs echo 2 > /sys/devices/cpu/rdpmc */ + +static inline uint64_t cpucycles(void) { + const uint32_t ecx = (1U << 30) + 1; + uint64_t result; + + __asm__ volatile ("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" + : "=a" (result) : "c" (ecx) : "rdx"); + + return result; +} + +#else + +static inline uint64_t cpucycles(void) { + uint64_t result; + + __asm__ volatile ("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" + : "=a" (result) : : "%rdx"); + + return result; +} + +#endif + +uint64_t cpucycles_overhead(void); + +#endif diff --git a/ref/test/speed_print.c b/ref/test/speed_print.c new file mode 100644 index 0000000..59f147d --- /dev/null +++ b/ref/test/speed_print.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include "cpucycles.h" +#include "speed_print.h" + +static int cmp_uint64(const void *a, const void *b) { + if(*(uint64_t *)a < *(uint64_t *)b) return -1; + if(*(uint64_t *)a > *(uint64_t *)b) return 1; + return 0; +} + +static uint64_t median(uint64_t *l, size_t llen) { + qsort(l,llen,sizeof(uint64_t),cmp_uint64); + + if(llen%2) return l[llen/2]; + else return (l[llen/2-1]+l[llen/2])/2; +} + +static uint64_t average(uint64_t *t, size_t tlen) { + size_t i; + uint64_t acc=0; + + for(i=0;i +#include + +void print_results(const char *s, uint64_t *t, size_t tlen); + +#endif diff --git a/ref/test/test_dilithium.c b/ref/test/test_dilithium.c new file mode 100644 index 0000000..66beb4c --- /dev/null +++ b/ref/test/test_dilithium.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include "../randombytes.h" +#include "../sign.h" + +#define MLEN 59 +#define CTXLEN 14 +#define NTESTS 10000 + +int main(void) +{ + size_t i, j; + int ret; + size_t mlen, smlen; + uint8_t b; + uint8_t ctx[CTXLEN] = {0}; + uint8_t m[MLEN + CRYPTO_BYTES]; + uint8_t m2[MLEN + CRYPTO_BYTES]; + uint8_t sm[MLEN + CRYPTO_BYTES]; + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + + snprintf((char*)ctx,CTXLEN,"test_dilitium"); + + for(i = 0; i < NTESTS; ++i) { + randombytes(m, MLEN); + + crypto_sign_keypair(pk, sk); + crypto_sign(sm, &smlen, m, MLEN, ctx, CTXLEN, sk); + ret = crypto_sign_open(m2, &mlen, sm, smlen, ctx, CTXLEN, pk); + + if(ret) { + fprintf(stderr, "Verification failed\n"); + return -1; + } + if(smlen != MLEN + CRYPTO_BYTES) { + fprintf(stderr, "Signed message lengths wrong\n"); + return -1; + } + if(mlen != MLEN) { + fprintf(stderr, "Message lengths wrong\n"); + return -1; + } + for(j = 0; j < MLEN; ++j) { + if(m2[j] != m[j]) { + fprintf(stderr, "Messages don't match\n"); + return -1; + } + } + + randombytes((uint8_t *)&j, sizeof(j)); + do { + randombytes(&b, 1); + } while(!b); + sm[j % (MLEN + CRYPTO_BYTES)] += b; + ret = crypto_sign_open(m2, &mlen, sm, smlen, ctx, CTXLEN, pk); + if(!ret) { + fprintf(stderr, "Trivial forgeries possible\n"); + return -1; + } + } + + printf("CRYPTO_PUBLICKEYBYTES = %d\n", CRYPTO_PUBLICKEYBYTES); + printf("CRYPTO_SECRETKEYBYTES = %d\n", CRYPTO_SECRETKEYBYTES); + printf("CRYPTO_BYTES = %d\n", CRYPTO_BYTES); + + return 0; +} diff --git a/ref/test/test_mul.c b/ref/test/test_mul.c new file mode 100644 index 0000000..4633c11 --- /dev/null +++ b/ref/test/test_mul.c @@ -0,0 +1,60 @@ +#include +#include +#include "../params.h" +#include "../randombytes.h" +#include "../poly.h" + +#define NTESTS 100000 + +static void poly_naivemul(poly *c, const poly *a, const poly *b) { + unsigned int i,j; + int32_t r[2*N] = {0}; + + for(i = 0; i < N; i++) + for(j = 0; j < N; j++) + r[i+j] = (r[i+j] + (int64_t)a->coeffs[i]*b->coeffs[j]) % Q; + + for(i = N; i < 2*N; i++) + r[i-N] = (r[i-N] - r[i]) % Q; + + for(i = 0; i < N; i++) + c->coeffs[i] = r[i]; +} + +int main(void) { + unsigned int i, j; + uint8_t seed[SEEDBYTES]; + uint16_t nonce = 0; + poly a, b, c, d; + + randombytes(seed, sizeof(seed)); + for(i = 0; i < NTESTS; ++i) { + poly_uniform(&a, seed, nonce++); + poly_uniform(&b, seed, nonce++); + + c = a; + poly_ntt(&c); + for(j = 0; j < N; ++j) + c.coeffs[j] = (int64_t)c.coeffs[j]*-114592 % Q; + poly_invntt_tomont(&c); + for(j = 0; j < N; ++j) { + if((c.coeffs[j] - a.coeffs[j]) % Q) + fprintf(stderr, "ERROR in ntt/invntt: c[%d] = %d != %d\n", + j, c.coeffs[j]%Q, a.coeffs[j]); + } + + poly_naivemul(&c, &a, &b); + poly_ntt(&a); + poly_ntt(&b); + poly_pointwise_montgomery(&d, &a, &b); + poly_invntt_tomont(&d); + + for(j = 0; j < N; ++j) { + if((d.coeffs[j] - c.coeffs[j]) % Q) + fprintf(stderr, "ERROR in multiplication: d[%d] = %d != %d\n", + j, d.coeffs[j], c.coeffs[j]); + } + } + + return 0; +} diff --git a/ref/test/test_speed.c b/ref/test/test_speed.c new file mode 100644 index 0000000..688d930 --- /dev/null +++ b/ref/test/test_speed.c @@ -0,0 +1,87 @@ +#include +#include "../sign.h" +#include "../poly.h" +#include "../polyvec.h" +#include "../params.h" +#include "cpucycles.h" +#include "speed_print.h" + +#define NTESTS 1000 + +uint64_t t[NTESTS]; + +int main(void) +{ + unsigned int i; + size_t siglen; + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t sig[CRYPTO_BYTES]; + uint8_t seed[CRHBYTES]; + polyvecl mat[K]; + poly *a = &mat[0].vec[0]; + poly *b = &mat[0].vec[1]; + poly *c = &mat[0].vec[2]; + + for(i = 0; i < NTESTS; ++i) { + t[i] = cpucycles(); + polyvec_matrix_expand(mat, seed); + } + print_results("polyvec_matrix_expand:", t, NTESTS); + + for(i = 0; i < NTESTS; ++i) { + t[i] = cpucycles(); + poly_uniform_eta(a, seed, 0); + } + print_results("poly_uniform_eta:", t, NTESTS); + + for(i = 0; i < NTESTS; ++i) { + t[i] = cpucycles(); + poly_uniform_gamma1(a, seed, 0); + } + print_results("poly_uniform_gamma1:", t, NTESTS); + + for(i = 0; i < NTESTS; ++i) { + t[i] = cpucycles(); + poly_ntt(a); + } + print_results("poly_ntt:", t, NTESTS); + + for(i = 0; i < NTESTS; ++i) { + t[i] = cpucycles(); + poly_invntt_tomont(a); + } + print_results("poly_invntt_tomont:", t, NTESTS); + + for(i = 0; i < NTESTS; ++i) { + t[i] = cpucycles(); + poly_pointwise_montgomery(c, a, b); + } + print_results("poly_pointwise_montgomery:", t, NTESTS); + + for(i = 0; i < NTESTS; ++i) { + t[i] = cpucycles(); + poly_challenge(c, seed); + } + print_results("poly_challenge:", t, NTESTS); + + for(i = 0; i < NTESTS; ++i) { + t[i] = cpucycles(); + crypto_sign_keypair(pk, sk); + } + print_results("Keypair:", t, NTESTS); + + for(i = 0; i < NTESTS; ++i) { + t[i] = cpucycles(); + crypto_sign_signature(sig, &siglen, sig, CRHBYTES, NULL, 0, sk); + } + print_results("Sign:", t, NTESTS); + + for(i = 0; i < NTESTS; ++i) { + t[i] = cpucycles(); + crypto_sign_verify(sig, CRYPTO_BYTES, sig, CRHBYTES, NULL, 0, pk); + } + print_results("Verify:", t, NTESTS); + + return 0; +} diff --git a/ref/test/test_vectors.c b/ref/test/test_vectors.c new file mode 100644 index 0000000..2829286 --- /dev/null +++ b/ref/test/test_vectors.c @@ -0,0 +1,251 @@ +#include +#include +#include +#include +#include "../randombytes.h" +#include "../fips202.h" +#include "../params.h" +#include "../sign.h" +#include "../poly.h" +#include "../polyvec.h" +#include "../packing.h" + +#define MLEN 32 +#define CTXLEN 13 +#define NVECTORS 10000 + +/* Initital state after absorbing empty string + * Permute before squeeze is achieved by setting pos to SHAKE128_RATE */ +static keccak_state rngstate = {{0x1F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (1ULL << 63), 0, 0, 0, 0}, SHAKE128_RATE}; + +void randombytes(uint8_t *x,size_t xlen) { + shake128_squeeze(x, xlen, &rngstate); +} + +int main(void) { + unsigned int i, j, k, l; + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t sig[CRYPTO_BYTES]; + uint8_t m[MLEN]; + uint8_t ctx[CTXLEN] = {0}; + uint8_t seed[CRHBYTES]; + uint8_t buf[CRYPTO_SECRETKEYBYTES]; + size_t siglen; + poly c, tmp; + polyvecl s, y, mat[K]; + polyveck w, w1, w0, t1, t0, h; + + snprintf((char*)ctx,CTXLEN,"test_vectors"); + + for(i = 0; i < NVECTORS; ++i) { + printf("count = %u\n", i); + + randombytes(m, MLEN); + printf("m = "); + for(j = 0; j < MLEN; ++j) + printf("%02x", m[j]); + printf("\n"); + + crypto_sign_keypair(pk, sk); + shake256(buf, 32, pk, CRYPTO_PUBLICKEYBYTES); + printf("pk = "); + for(j = 0; j < 32; ++j) + printf("%02x", buf[j]); + printf("\n"); + shake256(buf, 32, sk, CRYPTO_SECRETKEYBYTES); + printf("sk = "); + for(j = 0; j < 32; ++j) + printf("%02x", buf[j]); + printf("\n"); + + crypto_sign_signature(sig, &siglen, m, MLEN, ctx, CTXLEN, sk); + shake256(buf, 32, sig, CRYPTO_BYTES); + printf("sig = "); + for(j = 0; j < 32; ++j) + printf("%02x", buf[j]); + printf("\n"); + + if(crypto_sign_verify(sig, siglen, m, MLEN, ctx, CTXLEN, pk)) + fprintf(stderr,"Signature verification failed!\n"); + + randombytes(seed, sizeof(seed)); + printf("seed = "); + for(j = 0; j < sizeof(seed); ++j) + printf("%02X", seed[j]); + printf("\n"); + + polyvec_matrix_expand(mat, seed); + printf("A = (["); + for(j = 0; j < K; ++j) { + for(k = 0; k < L; ++k) { + for(l = 0; l < N; ++l) { + printf("%8d", mat[j].vec[k].coeffs[l]); + if(l < N-1) printf(", "); + else if(k < L-1) printf("], ["); + else if(j < K-1) printf("];\n ["); + else printf("])\n"); + } + } + } + + polyvecl_uniform_eta(&s, seed, 0); + + polyeta_pack(buf, &s.vec[0]); + polyeta_unpack(&tmp, buf); + for(j = 0; j < N; ++j) + if(tmp.coeffs[j] != s.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in polyeta_(un)pack!\n"); + + if(polyvecl_chknorm(&s, ETA+1)) + fprintf(stderr, "ERROR in polyvecl_chknorm(&s ,ETA+1)!\n"); + + printf("s = (["); + for(j = 0; j < L; ++j) { + for(k = 0; k < N; ++k) { + printf("%3d", s.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < L-1) printf("],\n ["); + else printf("])\n"); + } + } + + polyvecl_uniform_gamma1(&y, seed, 0); + + polyz_pack(buf, &y.vec[0]); + polyz_unpack(&tmp, buf); + for(j = 0; j < N; ++j) + if(tmp.coeffs[j] != y.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in polyz_(un)pack!\n"); + + if(polyvecl_chknorm(&y, GAMMA1+1)) + fprintf(stderr, "ERROR in polyvecl_chknorm(&y, GAMMA1)!\n"); + + printf("y = (["); + for(j = 0; j < L; ++j) { + for(k = 0; k < N; ++k) { + printf("%8d", y.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < L-1) printf("],\n ["); + else printf("])\n"); + } + } + + polyvecl_ntt(&y); + polyvec_matrix_pointwise_montgomery(&w, mat, &y); + polyveck_reduce(&w); + polyveck_invntt_tomont(&w); + polyveck_caddq(&w); + polyveck_decompose(&w1, &w0, &w); + + for(j = 0; j < N; ++j) { + tmp.coeffs[j] = w1.vec[0].coeffs[j]*2*GAMMA2 + w0.vec[0].coeffs[j]; + if(tmp.coeffs[j] < 0) tmp.coeffs[j] += Q; + if(tmp.coeffs[j] != w.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in poly_decompose!\n"); + } + + polyw1_pack(buf, &w1.vec[0]); +#if GAMMA2 == (Q-1)/32 + for(j = 0; j < N/2; ++j) { + tmp.coeffs[2*j+0] = buf[j] & 0xF; + tmp.coeffs[2*j+1] = buf[j] >> 4; + if(tmp.coeffs[2*j+0] != w1.vec[0].coeffs[2*j+0] + || tmp.coeffs[2*j+1] != w1.vec[0].coeffs[2*j+1]) + fprintf(stderr, "ERROR in polyw1_pack!\n"); + } +#endif + +#if GAMMA2 == (Q-1)/32 + if(polyveck_chknorm(&w1, 16)) + fprintf(stderr, "ERROR in polyveck_chknorm(&w1, 16)!\n"); +#elif GAMMA2 == (Q-1)/88 + if(polyveck_chknorm(&w1, 44)) + fprintf(stderr, "ERROR in polyveck_chknorm(&w1, 44)!\n"); +#endif + if(polyveck_chknorm(&w0, GAMMA2 + 1)) + fprintf(stderr, "ERROR in polyveck_chknorm(&w0, GAMMA2+1)!\n"); + + printf("w1 = (["); + for(j = 0; j < K; ++j) { + for(k = 0; k < N; ++k) { + printf("%2d", w1.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < K-1) printf("],\n ["); + else printf("])\n"); + } + } + printf("w0 = (["); + for(j = 0; j < K; ++j) { + for(k = 0; k < N; ++k) { + printf("%8d", w0.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < K-1) printf("],\n ["); + else printf("])\n"); + } + } + + polyveck_power2round(&t1, &t0, &w); + + for(j = 0; j < N; ++j) { + tmp.coeffs[j] = (t1.vec[0].coeffs[j] << D) + t0.vec[0].coeffs[j]; + if(tmp.coeffs[j] != w.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in poly_power2round!\n"); + } + + polyt1_pack(buf, &t1.vec[0]); + polyt1_unpack(&tmp, buf); + for(j = 0; j < N; ++j) { + if(tmp.coeffs[j] != t1.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in polyt1_(un)pack!\n"); + } + polyt0_pack(buf, &t0.vec[0]); + polyt0_unpack(&tmp, buf); + for(j = 0; j < N; ++j) { + if(tmp.coeffs[j] != t0.vec[0].coeffs[j]) + fprintf(stderr, "ERROR in polyt0_(un)pack!\n"); + } + + if(polyveck_chknorm(&t1, 1024)) + fprintf(stderr, "ERROR in polyveck_chknorm(&t1, 1024)!\n"); + if(polyveck_chknorm(&t0, (1U << (D-1)) + 1)) + fprintf(stderr, "ERROR in polyveck_chknorm(&t0, (1 << (D-1)) + 1)!\n"); + + printf("t1 = (["); + for(j = 0; j < K; ++j) { + for(k = 0; k < N; ++k) { + printf("%3d", t1.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < K-1) printf("],\n ["); + else printf("])\n"); + } + } + printf("t0 = (["); + for(j = 0; j < K; ++j) { + for(k = 0; k < N; ++k) { + printf("%5d", t0.vec[j].coeffs[k]); + if(k < N-1) printf(", "); + else if(j < K-1) printf("],\n ["); + else printf("])\n"); + } + } + + poly_challenge(&c, seed); + printf("c = ["); + for(j = 0; j < N; ++j) { + printf("%2d", c.coeffs[j]); + if(j < N-1) printf(", "); + else printf("]\n"); + } + + polyveck_make_hint(&h, &w0, &w1); + pack_sig(buf, seed, &y, &h); + unpack_sig(seed, &y, &w, buf); + if(memcmp(&h,&w,sizeof(h))) + fprintf(stderr, "ERROR in (un)pack_sig!\n"); + + printf("\n"); + } + + return 0; +} diff --git a/runlcov.sh b/runlcov.sh new file mode 100755 index 0000000..a94bb8b --- /dev/null +++ b/runlcov.sh @@ -0,0 +1,21 @@ +#!/bin/sh -e + +cd ref + +for alg in 2 3 5; do + make -B test/test_dilithium$alg CFLAGS="-O0 -g --coverage" + ./test/test_dilithium$alg + lcov -c -d . -o dilithium$alg.lcov + lcov -z -d . + rm test/test_dilithium$alg +done + +lcov -o dilithium.lcov \ + -a dilithium2.lcov \ + -a dilithium3.lcov \ + -a dilithium5.lcov \ + +lcov -r dilithium.lcov -o dilithium.lcov \ + '*/test/test_dilithium.c' + +exit 0 diff --git a/runtests.sh b/runtests.sh new file mode 100755 index 0000000..f0b0bc5 --- /dev/null +++ b/runtests.sh @@ -0,0 +1,33 @@ +#!/bin/sh -e +nproc="${nproc:-2}" + +ARCH="${ARCH:-amd64}" +ARCH="${TRAVIS_CPU_ARCH:-$ARCH}" + +if [ "$ARCH" = "amd64" -a "$TRAVIS_OS_NAME" != "osx" ]; then + DIRS="ref avx2" +else + DIRS="ref" +fi + +if [ "$ARCH" = "amd64" -o "$ARCH" = "arm64" ]; then + export CC=/usr/bin/clang + export CFLAGS="-fsanitize=undefined,address ${CFLAGS}" +fi + +for dir in $DIRS; do + make -j$(nproc) -C $dir clean + make -j$(nproc) -C $dir + for alg in 2 3 5; do + #valgrind --vex-guest-max-insns=25 ./$dir/test/test_dilithium$alg + ./$dir/test/test_dilithium$alg & + PID1=$! + echo testvec$alg + ./$dir/test/test_vectors$alg > tvecs$alg & + PID2=$! + wait $PID1 $PID2 + done + shasum -a256 -c SHA256SUMS +done + +exit 0 From e347d86bd40ad2eb78a6fa6524aa675a95760ac0 Mon Sep 17 00:00:00 2001 From: notmike Date: Tue, 3 Feb 2026 08:03:57 -0700 Subject: [PATCH 4/7] re-add cryptoquick's custom randombytes functions --- dilithium/ref/randombytes_custom.c | 12 ++++++++++++ sphincsplus/ref/randombytes_custom.c | 12 ++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 dilithium/ref/randombytes_custom.c create mode 100644 sphincsplus/ref/randombytes_custom.c diff --git a/dilithium/ref/randombytes_custom.c b/dilithium/ref/randombytes_custom.c new file mode 100644 index 0000000..2e661fc --- /dev/null +++ b/dilithium/ref/randombytes_custom.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include "randombytes.h" + +/* Forward declaration of our custom implementation from utils.c */ +extern void custom_randombytes_impl(uint8_t *out, size_t outlen); + +/* This function is the original randombytes implementation but calls our custom implementation */ +void randombytes(uint8_t *out, size_t outlen) { + custom_randombytes_impl(out, outlen); +} diff --git a/sphincsplus/ref/randombytes_custom.c b/sphincsplus/ref/randombytes_custom.c new file mode 100644 index 0000000..9c05aa3 --- /dev/null +++ b/sphincsplus/ref/randombytes_custom.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include "randombytes.h" + +/* Forward declaration of our custom implementation from utils.c */ +extern void custom_slh_randombytes_impl(uint8_t *out, size_t outlen); + +/* This function is the original randombytes implementation but calls our custom implementation */ +void randombytes(unsigned char *x, unsigned long long xlen) { + custom_slh_randombytes_impl(x, (size_t)xlen); +} From 5da0891af9eb7e42942843213a6988e8e83c55c0 Mon Sep 17 00:00:00 2001 From: jbride Date: Tue, 3 Feb 2026 09:58:09 -0700 Subject: [PATCH 5/7] user defined entropy refactoring. No longer need: - dilithium/ref/randombytes_custom.c - sphincsplus/ref/randombytes_custom.c Also includes documentation on how to test user provided entropy feature. --- CMakeLists.txt | 3 +- dilithium/ref/randombytes_custom.c | 12 -- docs/user_provided_entropy.md | 231 +++++++++++++++++++++++++++ examples/entropy_demo.c | 155 ++++++++++++++++++ nodejs/binding.gyp | 2 +- sphincsplus/ref/randombytes_custom.c | 12 -- src/ml_dsa/utils.c | 69 +------- src/randombytes_custom.c | 81 ++++++++++ src/randombytes_custom.h | 18 +++ src/slh_dsa/utils.c | 68 +------- 10 files changed, 494 insertions(+), 157 deletions(-) delete mode 100644 dilithium/ref/randombytes_custom.c create mode 100644 docs/user_provided_entropy.md create mode 100644 examples/entropy_demo.c delete mode 100644 sphincsplus/ref/randombytes_custom.c create mode 100644 src/randombytes_custom.c create mode 100644 src/randombytes_custom.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3efcb43..07ffa29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,8 +24,7 @@ include_directories( # Custom randombytes implementation set(CUSTOM_RANDOMBYTES - dilithium/ref/randombytes_custom.c - sphincsplus/ref/randombytes_custom.c + src/randombytes_custom.c ) # ML-DSA-44 (Dilithium) source files diff --git a/dilithium/ref/randombytes_custom.c b/dilithium/ref/randombytes_custom.c deleted file mode 100644 index 2e661fc..0000000 --- a/dilithium/ref/randombytes_custom.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include -#include "randombytes.h" - -/* Forward declaration of our custom implementation from utils.c */ -extern void custom_randombytes_impl(uint8_t *out, size_t outlen); - -/* This function is the original randombytes implementation but calls our custom implementation */ -void randombytes(uint8_t *out, size_t outlen) { - custom_randombytes_impl(out, outlen); -} diff --git a/docs/user_provided_entropy.md b/docs/user_provided_entropy.md new file mode 100644 index 0000000..bb76c4c --- /dev/null +++ b/docs/user_provided_entropy.md @@ -0,0 +1,231 @@ +# User-Provided Entropy + +libbitcoinpqc does not generate its own randomness. Instead, the caller is +responsible for supplying entropy to key generation functions. This document +explains why, what the library does with the entropy you provide, and how to +choose a suitable source. + +## Why "Bring Your Own Randomness"? + +Cryptographic key generation requires high-quality random data. Different +deployment environments have different trust models for where that randomness +should come from: + +- A Bitcoin node may already maintain its own CSPRNG seeded from multiple + hardware and OS sources. +- A regulated environment may require randomness from a FIPS 140-2/3 certified + HSM. +- An air-gapped signing device may use a dedicated hardware TRNG. +- A test harness may need deterministic keys from a fixed seed. + +By accepting entropy as a parameter rather than sourcing it internally, the +library avoids making assumptions about the caller's security requirements. + +## How the Library Consumes Entropy + +### ML-DSA-44 (CRYSTALS-Dilithium) + +`ml_dsa_44_keygen()` passes your entropy buffer to the internal Dilithium +reference implementation, which calls `randombytes(seedbuf, 32)` during key +generation. This means **32 bytes** of your provided data are consumed to +seed the key generation process. The seed is then expanded +deterministically by Dilithium's internal key derivation. + +### SLH-DSA-SHAKE-128s (SPHINCS+) + +`slh_dsa_shake_128s_keygen()` passes your entropy buffer directly to +`crypto_sign_seed_keypair()`, which uses the first `3 * SPX_N` bytes as the +seed. For SHAKE-128s, `SPX_N = 16`, so **48 bytes** are consumed. + +### The 128-Byte Minimum + +Both keygen functions reject buffers smaller than 128 bytes. This minimum +provides a comfortable margin above the actual consumption (32 or 48 bytes) +and ensures callers provide a meaningful amount of entropy rather than a +handful of bytes that might be poorly generated. + +### Determinism + +Providing identical entropy produces identical keys. This is by design: + +- It enables reproducible test vectors. +- It means the security of your keys depends entirely on the quality and + secrecy of the entropy you provide. + +### Entropy Cycling + +If the library's internal `randombytes()` requests exceed the size of your +buffer, the implementation wraps around to the beginning and reuses data. +With the 128-byte minimum and actual consumption of 32-48 bytes, this does +not occur during normal key generation. However, callers should be aware of +this behavior if using the lower-level APIs directly. + +## Choosing an Entropy Source + +### Requirements + +Your entropy source must be: + +1. **Unpredictable** - an attacker must not be able to guess or influence the + output. +2. **Sufficient entropy density** - the bytes you provide should contain close + to 8 bits of entropy per byte (i.e., indistinguishable from uniform random). +3. **Secret** - the entropy must not be logged, transmitted, or otherwise + exposed. + +### Suitable Sources + +**Operating system CSPRNG** - The simplest and most common choice. On Linux, +`/dev/urandom` or the `getrandom(2)` syscall provides kernel-mixed entropy +that is suitable for cryptographic use after the system has initialized. + +**Hardware Security Modules (HSMs)** - Devices such as Thales Luna, Utimaco +CryptoServer, or cloud-managed HSMs (AWS CloudHSM, Azure Dedicated HSM) +provide FIPS-certified hardware random number generation. Use these when +regulatory compliance requires a certified entropy source. + +**CPU hardware RNG** - Modern x86 processors expose the `RDRAND` and `RDSEED` +instructions, which draw from an on-die entropy source. ARM v8.5+ provides +the equivalent `RNDR` instruction. These can be used directly or as an +additional seed input to a CSPRNG. + +**Trusted Platform Modules (TPMs)** - TPM 2.0 chips, present in most +enterprise hardware, expose a hardware RNG accessible via `tpm2-tools` or +OS interfaces. Suitable as a supplementary entropy source. + +**Dedicated TRNGs / QRNGs** - Devices such as Quantis (ID Quantique) or +ComScire provide high-throughput true random number generation. Quantum RNGs +base their entropy on physical quantum processes. + +### Sources to Avoid + +- `rand()`, `random()`, or any userspace PRNG seeded from `time()` or PIDs. +- `/dev/random` when blocking behavior is undesirable (on modern Linux + kernels, `/dev/urandom` is equally suitable after initialization). +- Entropy gathered solely from low-resolution timers or predictable system + state. +- Network-based randomness beacons (e.g., NIST Beacon, drand) for secret key + material - these are public and unsuitable for keying. + +## Trying It Out on Linux + +This walkthrough builds the library from source, acquires entropy from the +command line, and pipes it into the included `examples/entropy_demo.c` +program. The demo reads exactly 128 bytes of entropy from **stdin**, then +generates ML-DSA-44 and SLH-DSA-SHAKE-128s key pairs, signs a message with +each, and verifies the signatures. + +### Prerequisites + +```bash +# Debian/Ubuntu +sudo apt-get install build-essential cmake + +# Fedora +sudo dnf install gcc gcc-c++ cmake make +``` + +### Step 1: Build the Library + +```bash +git clone https://github.com/bitcoin/libbitcoinpqc.git +cd libbitcoinpqc + +mkdir build && cd build +cmake .. +make +``` + +This produces `build/lib/libbitcoinpqc.a`. + +### Step 2: Compile the Demo + +```bash +cd .. +gcc -o /tmp/entropy_demo examples/entropy_demo.c \ + -Iinclude \ + -Lbuild/lib -lbitcoinpqc \ + -lm +``` + +### Step 3: Acquire Entropy and Run + +The demo expects exactly 128 bytes of raw entropy on stdin. There are +several ways to provide it from the command line. + +**Option A: `/dev/urandom` (simplest)** + +Read 128 bytes from the kernel CSPRNG and pipe them in: + +```bash +dd if=/dev/urandom bs=128 count=1 2>/dev/null | /tmp/entropy_demo +``` + +**Option B: OpenSSL** + +Use `openssl rand` to generate 128 cryptographically secure bytes: + +```bash +openssl rand 128 | /tmp/entropy_demo +``` + +**Option C: `getrandom(2)` via Python one-liner** + +Calls the `getrandom` syscall under the hood: + +```bash +python3 -c "import os,sys; sys.stdout.buffer.write(os.urandom(128))" | /tmp/entropy_demo +``` + +**Option D: Hardware RNG (`/dev/hwrng`)** + +If the system has a hardware TRNG exposed by the kernel (e.g., Intel +RDRAND via `rng-tools`, a TPM, or a USB TRNG): + +```bash +sudo dd if=/dev/hwrng bs=128 count=1 2>/dev/null | /tmp/entropy_demo +``` + +> Note: `/dev/hwrng` requires root or membership in the appropriate group. +> Not all systems expose this device by default; you may need to load the +> `rng-core` module or install `rng-tools`. + +Expected output (hex values will differ each run): + +``` +Entropy (first 16 bytes): 7a3f1c... + +ML-DSA-44 key pair generated successfully. + Public key size: 1312 bytes + Secret key size: 2560 bytes + Public key (first 16 bytes): 9b2e4d... + +Signature size: 2420 bytes +Verification: PASS + +SLH-DSA-SHAKE-128s key pair generated successfully. + Public key size: 32 bytes + Secret key size: 64 bytes + Public key (first 16 bytes): c4a81f... + +Signature size: 7856 bytes +Verification: PASS +``` + +### Step 4: Verify Determinism + +Save entropy to a file and feed it to the demo twice. The public key +bytes will be identical both times: + +```bash +dd if=/dev/urandom of=/tmp/saved_entropy.bin bs=128 count=1 2>/dev/null + +/tmp/entropy_demo < /tmp/saved_entropy.bin +/tmp/entropy_demo < /tmp/saved_entropy.bin +``` + +### Cleanup + +```bash +rm -f /tmp/entropy_demo saved_entropy.bin +``` diff --git a/examples/entropy_demo.c b/examples/entropy_demo.c new file mode 100644 index 0000000..7f2b653 --- /dev/null +++ b/examples/entropy_demo.c @@ -0,0 +1,155 @@ +/* + * entropy_demo.c - Demonstrates user-provided entropy with libbitcoinpqc. + * + * Reads exactly 128 bytes of entropy from stdin, then uses it to generate + * ML-DSA-44 and SLH-DSA-SHAKE-128s key pairs, sign a message, and verify + * the signatures. + * + * Usage: + * dd if=/dev/urandom bs=128 count=1 2>/dev/null | ./entropy_demo + * ./entropy_demo < saved_entropy.bin + */ + +#include +#include +#include +#include + +#define ENTROPY_SIZE 128 + +int main(void) { + uint8_t entropy[ENTROPY_SIZE]; + size_t total = 0; + + /* Read exactly ENTROPY_SIZE bytes from stdin */ + while (total < ENTROPY_SIZE) { + size_t n = fread(entropy + total, 1, ENTROPY_SIZE - total, stdin); + if (n == 0) { + fprintf(stderr, + "Error: need %d bytes of entropy on stdin, got %zu\n", + ENTROPY_SIZE, total); + return 1; + } + total += n; + } + + /* Show a hex preview of the entropy received */ + printf("Entropy (first 16 bytes): "); + for (int i = 0; i < 16; i++) { + printf("%02x", entropy[i]); + } + printf("...\n\n"); + + /* Generate an ML-DSA-44 key pair */ + bitcoin_pqc_keypair_t keypair; + bitcoin_pqc_error_t err = bitcoin_pqc_keygen( + BITCOIN_PQC_ML_DSA_44, &keypair, entropy, ENTROPY_SIZE + ); + + if (err != BITCOIN_PQC_OK) { + fprintf(stderr, "Key generation failed: %d\n", err); + return 1; + } + + printf("ML-DSA-44 key pair generated successfully.\n"); + printf(" Public key size: %zu bytes\n", keypair.public_key_size); + printf(" Secret key size: %zu bytes\n", keypair.secret_key_size); + + const uint8_t *pk = (const uint8_t *)keypair.public_key; + printf(" Public key (first 16 bytes): "); + for (int i = 0; i < 16; i++) { + printf("%02x", pk[i]); + } + printf("...\n\n"); + + /* Sign a message */ + const char *msg_text = "Hello, post-quantum world!"; + const uint8_t *message = (const uint8_t *)msg_text; + size_t message_len = strlen(msg_text); + + bitcoin_pqc_signature_t sig; + err = bitcoin_pqc_sign( + BITCOIN_PQC_ML_DSA_44, + keypair.secret_key, keypair.secret_key_size, + message, message_len, + &sig + ); + + if (err != BITCOIN_PQC_OK) { + fprintf(stderr, "Signing failed: %d\n", err); + bitcoin_pqc_keypair_free(&keypair); + return 1; + } + + printf("Signature size: %zu bytes\n", sig.signature_size); + + /* Verify the signature */ + err = bitcoin_pqc_verify( + BITCOIN_PQC_ML_DSA_44, + keypair.public_key, keypair.public_key_size, + message, message_len, + sig.signature, sig.signature_size + ); + + printf("Verification: %s\n\n", err == BITCOIN_PQC_OK ? "PASS" : "FAIL"); + + bitcoin_pqc_signature_free(&sig); + bitcoin_pqc_keypair_free(&keypair); + + if (err != BITCOIN_PQC_OK) + return 1; + + /* Generate an SLH-DSA-SHAKE-128s key pair using the same entropy */ + bitcoin_pqc_keypair_t slh_keypair; + err = bitcoin_pqc_keygen( + BITCOIN_PQC_SLH_DSA_SHAKE_128S, &slh_keypair, entropy, ENTROPY_SIZE + ); + + if (err != BITCOIN_PQC_OK) { + fprintf(stderr, "SLH-DSA key generation failed: %d\n", err); + return 1; + } + + printf("SLH-DSA-SHAKE-128s key pair generated successfully.\n"); + printf(" Public key size: %zu bytes\n", slh_keypair.public_key_size); + printf(" Secret key size: %zu bytes\n", slh_keypair.secret_key_size); + + const uint8_t *slh_pk = (const uint8_t *)slh_keypair.public_key; + printf(" Public key (first 16 bytes): "); + for (int i = 0; i < 16; i++) { + printf("%02x", slh_pk[i]); + } + printf("...\n\n"); + + /* Sign with SLH-DSA */ + bitcoin_pqc_signature_t slh_sig; + err = bitcoin_pqc_sign( + BITCOIN_PQC_SLH_DSA_SHAKE_128S, + slh_keypair.secret_key, slh_keypair.secret_key_size, + message, message_len, + &slh_sig + ); + + if (err != BITCOIN_PQC_OK) { + fprintf(stderr, "SLH-DSA signing failed: %d\n", err); + bitcoin_pqc_keypair_free(&slh_keypair); + return 1; + } + + printf("Signature size: %zu bytes\n", slh_sig.signature_size); + + /* Verify the SLH-DSA signature */ + err = bitcoin_pqc_verify( + BITCOIN_PQC_SLH_DSA_SHAKE_128S, + slh_keypair.public_key, slh_keypair.public_key_size, + message, message_len, + slh_sig.signature, slh_sig.signature_size + ); + + printf("Verification: %s\n", err == BITCOIN_PQC_OK ? "PASS" : "FAIL"); + + bitcoin_pqc_signature_free(&slh_sig); + bitcoin_pqc_keypair_free(&slh_keypair); + + return (err != BITCOIN_PQC_OK); +} diff --git a/nodejs/binding.gyp b/nodejs/binding.gyp index f10e710..e9d385e 100644 --- a/nodejs/binding.gyp +++ b/nodejs/binding.gyp @@ -22,7 +22,7 @@ "src/c_sources/dilithium_ref/rounding.c", "src/c_sources/dilithium_ref/fips202.c", "src/c_sources/dilithium_ref/symmetric-shake.c", - "src/c_sources/dilithium_ref/randombytes_custom.c", + "src/c_sources/randombytes_custom.c", "src/c_sources/sphincsplus_ref/address.c", "src/c_sources/sphincsplus_ref/fors.c", "src/c_sources/sphincsplus_ref/hash_shake.c", diff --git a/sphincsplus/ref/randombytes_custom.c b/sphincsplus/ref/randombytes_custom.c deleted file mode 100644 index 9c05aa3..0000000 --- a/sphincsplus/ref/randombytes_custom.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include -#include "randombytes.h" - -/* Forward declaration of our custom implementation from utils.c */ -extern void custom_slh_randombytes_impl(uint8_t *out, size_t outlen); - -/* This function is the original randombytes implementation but calls our custom implementation */ -void randombytes(unsigned char *x, unsigned long long xlen) { - custom_slh_randombytes_impl(x, (size_t)xlen); -} diff --git a/src/ml_dsa/utils.c b/src/ml_dsa/utils.c index a74d493..32caef3 100644 --- a/src/ml_dsa/utils.c +++ b/src/ml_dsa/utils.c @@ -1,27 +1,20 @@ #include #include #include -#include "../../dilithium/ref/randombytes.h" #include "../../dilithium/ref/api.h" #include "../../dilithium/ref/fips202.h" #include "../../dilithium/ref/params.h" #include "libbitcoinpqc/ml_dsa.h" +#include "../randombytes_custom.h" /* * This file implements utility functions for ML-DSA-44 (CRYSTALS-Dilithium) * particularly related to random data handling */ -/* Provide a custom random bytes function that uses user-provided entropy */ -static const uint8_t *g_random_data = NULL; -static size_t g_random_data_size = 0; -static size_t g_random_data_offset = 0; - /* Initialize the random data source */ void ml_dsa_init_random_source(const uint8_t *random_data, size_t random_data_size) { - g_random_data = random_data; - g_random_data_size = random_data_size; - g_random_data_offset = 0; + pqc_randombytes_init(random_data, random_data_size); } /* Setup custom random function - this is called before keygen/sign */ @@ -31,63 +24,7 @@ void ml_dsa_setup_custom_random() { /* Restore original random function - this is called after keygen/sign */ void ml_dsa_restore_original_random() { - /* Clear the global state */ - g_random_data = NULL; - g_random_data_size = 0; - g_random_data_offset = 0; -} - -/* This function is called from our custom randombytes implementation */ -void custom_randombytes_impl(uint8_t *out, size_t outlen) { - /* If out is NULL or outlen is 0, nothing to do */ - if (!out || outlen == 0) { - return; - } - - /* If we don't have custom random data, use system randomness */ - if (g_random_data == NULL || g_random_data_size == 0) { - /* Fall back to system randomness */ - FILE *f = fopen("/dev/urandom", "r"); - if (!f) { - /* If we can't open /dev/urandom, just fill with zeros */ - memset(out, 0, outlen); - return; - } - - size_t bytes_read = fread(out, 1, outlen, f); - fclose(f); - - /* If we can't read enough data, fill remaining with zeros */ - if (bytes_read < outlen) { - memset(out + bytes_read, 0, outlen - bytes_read); - } - - return; - } - - /* Otherwise use our provided random data */ - size_t total_copied = 0; - - /* Copy data until we've filled the output buffer */ - while (total_copied < outlen) { - /* Calculate amount to copy */ - size_t amount = outlen - total_copied; - if (amount > g_random_data_size - g_random_data_offset) { - amount = g_random_data_size - g_random_data_offset; - } - - /* Copy the data */ - memcpy(out + total_copied, g_random_data + g_random_data_offset, amount); - - /* Update positions */ - total_copied += amount; - g_random_data_offset += amount; - - /* Wrap around if needed */ - if (g_random_data_offset >= g_random_data_size) { - g_random_data_offset = 0; - } - } + pqc_randombytes_cleanup(); } /* Function to derive deterministic randomness from message and key */ diff --git a/src/randombytes_custom.c b/src/randombytes_custom.c new file mode 100644 index 0000000..97b5a89 --- /dev/null +++ b/src/randombytes_custom.c @@ -0,0 +1,81 @@ +/* + * Consolidated custom randombytes implementation. + * + * Provides the single randombytes() definition used by both the Dilithium + * and SPHINCS+ reference implementations. User-provided entropy is + * injected via pqc_randombytes_init(); when no custom data is set the + * function falls back to /dev/urandom. + * + * The Dilithium-style signature (uint8_t*, size_t) is used here. It is + * ABI-compatible with the SPHINCS+ signature (unsigned char*, + * unsigned long long) on LP64 platforms. + */ + +#include +#include +#include +#include +#include "randombytes_custom.h" + +/* Global entropy state */ +static const uint8_t *g_random_data = NULL; +static size_t g_random_data_size = 0; +static size_t g_random_data_offset = 0; + +void pqc_randombytes_init(const uint8_t *data, size_t size) { + g_random_data = data; + g_random_data_size = size; + g_random_data_offset = 0; +} + +void pqc_randombytes_cleanup(void) { + g_random_data = NULL; + g_random_data_size = 0; + g_random_data_offset = 0; +} + +/* + * randombytes() — called by the upstream Dilithium and SPHINCS+ reference + * implementations during keygen and signing. + */ +void randombytes(uint8_t *out, size_t outlen) { + if (!out || outlen == 0) { + return; + } + + /* No custom data: fall back to system randomness */ + if (g_random_data == NULL || g_random_data_size == 0) { + FILE *f = fopen("/dev/urandom", "r"); + if (!f) { + memset(out, 0, outlen); + return; + } + + size_t bytes_read = fread(out, 1, outlen, f); + fclose(f); + + if (bytes_read < outlen) { + memset(out + bytes_read, 0, outlen - bytes_read); + } + return; + } + + /* Serve from user-provided buffer, cycling if necessary */ + size_t total_copied = 0; + + while (total_copied < outlen) { + size_t amount = outlen - total_copied; + if (amount > g_random_data_size - g_random_data_offset) { + amount = g_random_data_size - g_random_data_offset; + } + + memcpy(out + total_copied, g_random_data + g_random_data_offset, amount); + + total_copied += amount; + g_random_data_offset += amount; + + if (g_random_data_offset >= g_random_data_size) { + g_random_data_offset = 0; + } + } +} diff --git a/src/randombytes_custom.h b/src/randombytes_custom.h new file mode 100644 index 0000000..37e42f2 --- /dev/null +++ b/src/randombytes_custom.h @@ -0,0 +1,18 @@ +#ifndef PQC_RANDOMBYTES_CUSTOM_H +#define PQC_RANDOMBYTES_CUSTOM_H + +#include +#include + +/* + * Shared entropy state for user-provided randomness. + * + * Call pqc_randombytes_init() before invoking any upstream keygen/sign + * function that calls randombytes(), and pqc_randombytes_cleanup() + * afterwards to clear the global state. + */ + +void pqc_randombytes_init(const uint8_t *data, size_t size); +void pqc_randombytes_cleanup(void); + +#endif /* PQC_RANDOMBYTES_CUSTOM_H */ diff --git a/src/slh_dsa/utils.c b/src/slh_dsa/utils.c index 9bf6303..7d37f07 100644 --- a/src/slh_dsa/utils.c +++ b/src/slh_dsa/utils.c @@ -2,7 +2,6 @@ #include #include #include -#include "../../sphincsplus/ref/randombytes.h" #include "../../sphincsplus/ref/api.h" #include "../../sphincsplus/ref/fors.h" #include "../../sphincsplus/ref/hash.h" @@ -10,85 +9,26 @@ #include "../../sphincsplus/ref/utils.h" #include "../../sphincsplus/ref/address.h" #include "libbitcoinpqc/slh_dsa.h" +#include "../randombytes_custom.h" /* * This file implements utility functions for SLH-DSA-Shake-128s (SPHINCS+) * particularly related to random data handling */ -/* Provide a custom random bytes function that uses user-provided entropy */ -static const uint8_t *g_random_data = NULL; -static size_t g_random_data_size = 0; -static size_t g_random_data_offset = 0; - /* Initialize the random data source */ void slh_dsa_init_random_source(const uint8_t *random_data, size_t random_data_size) { - g_random_data = random_data; - g_random_data_size = random_data_size; - - /* Always reset offset to ensure deterministic behavior */ - g_random_data_offset = 0; - - /* Note: For truly deterministic behavior across multiple calls, - * we should hash the random data with some constant seed, but - * for this implementation we'll just use the raw data. - */ + pqc_randombytes_init(random_data, random_data_size); } /* Setup custom random function - this is called before keygen/sign */ void slh_dsa_setup_custom_random() { - /* Nothing to do here, as we can't replace the function */ + /* Nothing to do here, as our randombytes function is already set up */ } /* Restore original random function - this is called after keygen/sign */ void slh_dsa_restore_original_random() { - /* Clear the global state */ - g_random_data = NULL; - g_random_data_size = 0; - g_random_data_offset = 0; -} - -/* This function is called from our custom randombytes implementation */ -void custom_slh_randombytes_impl(uint8_t *out, size_t outlen) { - /* If we don't have custom random data, use system randomness */ - if (g_random_data == NULL || g_random_data_size == 0) { - /* Fall back to system randomness */ - FILE *f = fopen("/dev/urandom", "r"); - if (!f) { - /* If we can't open /dev/urandom, just fill with zeros */ - memset(out, 0, outlen); - return; - } - - if (fread(out, 1, outlen, f) != outlen) { - /* If we can't read enough data, fill remaining with zeros */ - memset(out, 0, outlen); - } - - fclose(f); - return; - } - - /* Otherwise use our provided random data */ - size_t remaining = g_random_data_size - g_random_data_offset; - - if (outlen > remaining) { - /* If we need more random bytes than available, we cycle through the provided data */ - size_t position = 0; - - while (position < outlen) { - size_t to_copy = (outlen - position < remaining) ? outlen - position : remaining; - memcpy(out + position, g_random_data + g_random_data_offset, to_copy); - - position += to_copy; - g_random_data_offset = (g_random_data_offset + to_copy) % g_random_data_size; - remaining = g_random_data_size - g_random_data_offset; - } - } else { - /* We have enough random data */ - memcpy(out, g_random_data + g_random_data_offset, outlen); - g_random_data_offset = (g_random_data_offset + outlen) % g_random_data_size; - } + pqc_randombytes_cleanup(); } /* Simple implementation of deterministic randomness from message and key */ From 802e1c2a6b1bbd0bdbbd66f343784c1b9b1ba594 Mon Sep 17 00:00:00 2001 From: jbride Date: Tue, 3 Feb 2026 17:10:58 -0700 Subject: [PATCH 6/7] segregating core C functionality from language bindings (which will all go in a different git repository --- .github/workflows/ci.yml | 77 +- .gitignore | 8 - .vscode/settings.json | 5 +- Cargo.lock | 1040 ---- Cargo.toml | 46 - Makefile | 169 +- README.md | 210 +- benches/README.md | 89 - benches/REPORT.md | 31 - benches/sig_benchmarks.rs | 479 -- build.rs | 40 - examples/basic.rs | 77 - fuzz/.gitignore | 3 - fuzz/Cargo.lock | 505 -- fuzz/Cargo.toml | 54 - fuzz/README.md | 83 - ...h-256ac14220a2ca53e6006f2ed7f036b98864e08a | Bin 155 -> 0 bytes fuzz/fuzz_targets/cross_algorithm_fuzz.rs | 66 - fuzz/fuzz_targets/key_parsing_fuzz.rs | 40 - fuzz/fuzz_targets/keypair_generation_fuzz.rs | 28 - fuzz/fuzz_targets/sign_verify_fuzz.rs | 77 - fuzz/fuzz_targets/signature_parsing_fuzz.rs | 22 - fuzz/output.txt | 176 - fuzz/run_all_fuzzers.sh | 29 - nodejs/.gitignore | 25 - nodejs/README.md | 167 - nodejs/binding.gyp | 79 - nodejs/examples/basic-usage.ts | 92 - nodejs/jest.config.js | 8 - nodejs/package-lock.json | 4968 ----------------- nodejs/package.json | 60 - nodejs/scripts/sync-c-sources.sh | 41 - nodejs/src/__tests__/bitcoinpqc.test.ts | 149 - nodejs/src/index.ts | 171 - nodejs/src/library.ts | 187 - nodejs/src/native/bitcoinpqc_addon.cc | 208 - nodejs/src/native/bitcoinpqc_wrapper.cc | 171 - nodejs/src/native/bitcoinpqc_wrapper.h | 17 - nodejs/src/native/mock_bitcoinpqc_addon.cc | 305 - nodejs/src/types.ts | 125 - nodejs/tests/bitcoinpqc.test.ts | 153 - nodejs/tsconfig.json | 116 - python/MANIFEST.in | 4 - python/README.md | 77 - python/bitcoinpqc/__init__.py | 21 - python/bitcoinpqc/bitcoinpqc.py | 533 -- python/check_library.py | 102 - python/examples/__init__.py | 1 - python/examples/basic_usage.py | 65 - python/run_tests.sh | 45 - python/setup.py | 38 - python/tests/__init__.py | 1 - python/tests/test_bitcoinpqc.py | 77 - src/bindings_include.rs | 207 - src/lib.rs | 698 --- tests/algorithm_tests.rs | 316 -- tests/serialization_tests.rs | 447 -- 57 files changed, 38 insertions(+), 12990 deletions(-) delete mode 100644 Cargo.lock delete mode 100644 Cargo.toml delete mode 100644 benches/README.md delete mode 100644 benches/REPORT.md delete mode 100644 benches/sig_benchmarks.rs delete mode 100644 build.rs delete mode 100644 examples/basic.rs delete mode 100644 fuzz/.gitignore delete mode 100644 fuzz/Cargo.lock delete mode 100644 fuzz/Cargo.toml delete mode 100644 fuzz/README.md delete mode 100644 fuzz/artifacts/sign_verify/crash-256ac14220a2ca53e6006f2ed7f036b98864e08a delete mode 100644 fuzz/fuzz_targets/cross_algorithm_fuzz.rs delete mode 100644 fuzz/fuzz_targets/key_parsing_fuzz.rs delete mode 100644 fuzz/fuzz_targets/keypair_generation_fuzz.rs delete mode 100644 fuzz/fuzz_targets/sign_verify_fuzz.rs delete mode 100644 fuzz/fuzz_targets/signature_parsing_fuzz.rs delete mode 100644 fuzz/output.txt delete mode 100755 fuzz/run_all_fuzzers.sh delete mode 100644 nodejs/.gitignore delete mode 100644 nodejs/README.md delete mode 100644 nodejs/binding.gyp delete mode 100644 nodejs/examples/basic-usage.ts delete mode 100644 nodejs/jest.config.js delete mode 100644 nodejs/package-lock.json delete mode 100644 nodejs/package.json delete mode 100755 nodejs/scripts/sync-c-sources.sh delete mode 100644 nodejs/src/__tests__/bitcoinpqc.test.ts delete mode 100644 nodejs/src/index.ts delete mode 100644 nodejs/src/library.ts delete mode 100644 nodejs/src/native/bitcoinpqc_addon.cc delete mode 100644 nodejs/src/native/bitcoinpqc_wrapper.cc delete mode 100644 nodejs/src/native/bitcoinpqc_wrapper.h delete mode 100644 nodejs/src/native/mock_bitcoinpqc_addon.cc delete mode 100644 nodejs/src/types.ts delete mode 100644 nodejs/tests/bitcoinpqc.test.ts delete mode 100644 nodejs/tsconfig.json delete mode 100644 python/MANIFEST.in delete mode 100644 python/README.md delete mode 100644 python/bitcoinpqc/__init__.py delete mode 100644 python/bitcoinpqc/bitcoinpqc.py delete mode 100755 python/check_library.py delete mode 100644 python/examples/__init__.py delete mode 100644 python/examples/basic_usage.py delete mode 100755 python/run_tests.sh delete mode 100644 python/setup.py delete mode 100644 python/tests/__init__.py delete mode 100644 python/tests/test_bitcoinpqc.py delete mode 100644 src/bindings_include.rs delete mode 100644 src/lib.rs delete mode 100644 tests/algorithm_tests.rs delete mode 100644 tests/serialization_tests.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f3d9bfa..52d4d53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Rust CI +name: C CI on: push: @@ -6,12 +6,9 @@ on: pull_request: branches: [ main ] -env: - CARGO_TERM_COLOR: always - jobs: - test: - name: Test + build: + name: Build and Test runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -21,25 +18,17 @@ jobs: sudo apt-get update sudo apt-get install -y build-essential cmake libssl-dev - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - components: clippy, rustfmt - - - name: Cache dependencies - uses: Swatinem/rust-cache@v2 - - - name: Check code format - run: cargo fmt -- --check - - - name: Clippy - run: cargo clippy -- -D warnings + - name: Configure + run: | + mkdir build + cd build + cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=ON - name: Build - run: cargo build --verbose + run: cmake --build build --verbose - name: Run tests - run: cargo test --verbose + run: cd build && ctest -V build-matrix: name: Build on ${{ matrix.os }} @@ -48,7 +37,6 @@ jobs: matrix: os: [ubuntu-latest] # os: [ubuntu-latest, macos-latest] - rust: [stable] fail-fast: false steps: - uses: actions/checkout@v3 @@ -64,45 +52,14 @@ jobs: run: | brew install cmake - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - toolchain: ${{ matrix.rust }} - components: clippy, rustfmt - - - name: Cache dependencies - uses: Swatinem/rust-cache@v2 - - - name: Check code format - run: cargo fmt -- --check - - - name: Clippy - run: cargo clippy -- -D warnings + - name: Configure + run: | + mkdir build + cd build + cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=ON - name: Build - run: cargo build --verbose + run: cmake --build build --verbose - name: Run tests - run: cargo test --verbose - - # benchmark: - # name: Benchmark - # runs-on: ubuntu-latest - # needs: test - # if: github.event_name == 'push' && github.ref == 'refs/heads/main' - # steps: - # - uses: actions/checkout@v3 - - # - name: Install dependencies - # run: | - # sudo apt-get update - # sudo apt-get install -y build-essential cmake libssl-dev - - # - name: Install Rust - # uses: dtolnay/rust-toolchain@stable - - # - name: Cache dependencies - # uses: Swatinem/rust-cache@v2 - - # - name: Run benchmarks - # run: cargo bench + run: cd build && ctest -V diff --git a/.gitignore b/.gitignore index 37d93e8..f327811 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,7 @@ build/ -dist/ *.o benchmark_results.txt -__pycache__ -python/build/ -*.egg-info/ -node_modules/ **.gcno **.lcov -**/target/ tags TAGS -rust-toolchain.toml -Cargo.lock \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 206a107..ad92582 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,3 @@ { - "rust-analyzer.cargo.features": ["ide"], - "editor.formatOnSave": true, - "rust-analyzer.check.command": "clippy", - "rust-analyzer.check.extraArgs": ["--all-targets"] + "editor.formatOnSave": true } diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 7a41a75..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,1040 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - -[[package]] -name = "anstyle" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "bindgen" -version = "0.71.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn", -] - -[[package]] -name = "bitcoin-io" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" - -[[package]] -name = "bitcoin_hashes" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" -dependencies = [ - "bitcoin-io", - "hex-conservative", -] - -[[package]] -name = "bitcoinpqc" -version = "0.2.0" -dependencies = [ - "bindgen", - "bitmask-enum", - "cmake", - "criterion", - "hex", - "libc", - "rand", - "secp256k1", - "serde", - "serde_json", - "sha2", -] - -[[package]] -name = "bitflags" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" - -[[package]] -name = "bitmask-enum" -version = "2.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6cbbb8f56245b5a479b30a62cdc86d26e2f35c2b9f594bc4671654b03851380" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bumpalo" -version = "3.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cc" -version = "1.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" -dependencies = [ - "shlex", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" - -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "4.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" -dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" -dependencies = [ - "anstyle", - "clap_lex", -] - -[[package]] -name = "clap_lex" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "criterion" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" -dependencies = [ - "anes", - "cast", - "ciborium", - "clap", - "criterion-plot", - "is-terminal", - "itertools 0.10.5", - "num-traits", - "once_cell", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools 0.10.5", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi", -] - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "half" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" -dependencies = [ - "cfg-if", - "crunchy", -] - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex-conservative" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" -dependencies = [ - "arrayvec", -] - -[[package]] -name = "is-terminal" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "libc" -version = "0.2.174" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" - -[[package]] -name = "libloading" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" -dependencies = [ - "cfg-if", - "windows-targets 0.53.2", -] - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "memchr" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "oorandom" -version = "11.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" - -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "prettyplease" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "rand" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustversion" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "secp256k1" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3dff2d01c9aa65c3186a45ff846bfea52cbe6de3b6320ed2a358d90dad0d76" -dependencies = [ - "bitcoin_hashes", - "rand", - "secp256k1-sys", - "serde", -] - -[[package]] -name = "secp256k1-sys" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb913707158fadaf0d8702c2db0e857de66eb003ccfdda5924b5f5ac98efb38" -dependencies = [ - "cc", -] - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "syn" -version = "2.0.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "web-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "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]] -name = "windows_aarch64_gnullvm" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] - -[[package]] -name = "zerocopy" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 338a9b5..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,46 +0,0 @@ -[package] -name = "bitcoinpqc" -version = "0.2.0" -edition = "2021" -authors = ["Hunter Beast "] -description = "Post-Quantum Cryptographic signature algorithms for Bitcoin (BIP-360)" -repository = "https://github.com/bitcoin/libbitcoinpqc" -license = "MIT" -keywords = ["bitcoin", "pqc", "cryptography", "bip-360", "qubit"] - -[dependencies] -hex = "0.4" -libc = "0.2" -bitmask-enum = "2.2.5" -serde = { version = "1.0", features = ["derive"], optional = true } -secp256k1 = { version = "0.31.0", default-features = false, features = [ - "global-context", - "rand", -] } - -[build-dependencies] -bindgen = "0.71.1" -cmake = "0.1" - -[dev-dependencies] -hex = "0.4" -rand = "0.9" -criterion = "0.5" -sha2 = "0.10" -serde_json = "1.0" - -[features] -default = [] -# Enable this feature in your IDE for better code completion -# but never use it for actual builds -ide = [] -# Define the serde feature -serde = ["dep:serde", "secp256k1/serde"] - -[lib] -name = "bitcoinpqc" -crate-type = ["rlib", "staticlib", "cdylib"] - -[[bench]] -name = "sig_benchmarks" -harness = false diff --git a/Makefile b/Makefile index 14ab0d5..9fd8e8a 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,17 @@ # libbitcoinpqc - Post-Quantum Cryptography for Bitcoin -# Main Makefile for building, testing, and installing all components +# Main Makefile for building, testing, and installing the C library # User-configurable variables PREFIX ?= /usr/local DEBUG ?= 0 VERBOSE ?= 0 -INSTALL_DEPS ?= 0 -BUILD_DOCS ?= 0 NO_COLOR ?= 0 -BUILD_BINDINGS ?= 0 # Tool detection CMAKE := $(shell command -v cmake 2> /dev/null) -CARGO := $(shell command -v cargo 2> /dev/null) -PYTHON := $(shell command -v python3 2> /dev/null) -NPM := $(shell command -v npm 2> /dev/null) # Build directories BUILD_DIR := build -RELEASE_DIR := target/release -DEBUG_DIR := target/debug # Colors for terminal output ifeq ($(NO_COLOR), 0) @@ -38,14 +30,10 @@ endif # Default target .PHONY: all -all: info c-lib rust-lib bindings +all: info c-lib .PHONY: everything -everything: all examples tests docs - -# Bindings target -.PHONY: bindings -bindings: python nodejs +everything: all examples tests # Print build information .PHONY: info @@ -53,17 +41,11 @@ info: @echo -e "${BLUE}Building libbitcoinpqc - Post-Quantum Cryptography for Bitcoin${NC}" @echo -e "${BLUE}------------------------------------------------------------${NC}" @if [ -n "$(CMAKE)" ]; then echo -e " [${GREEN}✓${NC}] CMake: $(CMAKE)"; else echo -e " [${RED}✗${NC}] CMake (required for C library)"; fi - @if [ -n "$(CARGO)" ]; then echo -e " [${GREEN}✓${NC}] Cargo: $(CARGO)"; else echo -e " [${RED}✗${NC}] Cargo (required for Rust library)"; fi - @if [ -n "$(PYTHON)" ]; then echo -e " [${GREEN}✓${NC}] Python: $(PYTHON)"; else echo -e " [${YELLOW}!${NC}] Python (optional for Python bindings)"; fi - @if [ -n "$(NPM)" ]; then echo -e " [${GREEN}✓${NC}] NPM: $(NPM)"; else echo -e " [${YELLOW}!${NC}] NPM (optional for NodeJS bindings)"; fi @echo -e "${BLUE}------------------------------------------------------------${NC}" - @echo -e "${YELLOW}This will build the core libraries (C and Rust) and language bindings.${NC}" @echo -e "${YELLOW}Available make targets:${NC}" - @echo -e " ${GREEN}make c-lib${NC} - Build only the C library" - @echo -e " ${GREEN}make rust-lib${NC} - Build only the Rust library" - @echo -e " ${GREEN}make bindings${NC} - Build only Python and NodeJS bindings" + @echo -e " ${GREEN}make c-lib${NC} - Build the C library" @echo -e " ${GREEN}make examples${NC} - Build example programs" - @echo -e " ${GREEN}make everything${NC} - Build all components (libraries, bindings, examples, tests)" + @echo -e " ${GREEN}make everything${NC} - Build all components (library, examples, tests)" @echo -e " ${GREEN}make help${NC} - Show all available targets" @echo -e "${BLUE}------------------------------------------------------------${NC}" @@ -82,135 +64,45 @@ cmake-build: @echo -e "${BLUE}Building C library...${NC}" @cmake --build $(BUILD_DIR) $(if $(filter 1,$(VERBOSE)),--verbose,) -# Rust library targets -.PHONY: rust-lib -rust-lib: - @echo -e "${BLUE}Building Rust library...${NC}" - @$(CARGO) build $(if $(filter 0,$(DEBUG)),--release,) - # Example targets .PHONY: examples -examples: c-examples rust-examples - -.PHONY: c-examples -c-examples: c-lib +examples: c-lib @echo -e "${BLUE}Building C examples...${NC}" @cmake --build $(BUILD_DIR) --target examples -.PHONY: rust-examples -rust-examples: - @echo -e "${BLUE}Building and running Rust examples...${NC}" - @$(CARGO) run --example basic $(if $(filter 0,$(DEBUG)),--release,) - # Testing targets .PHONY: tests -tests: test-c test-rust +tests: test-c .PHONY: test-c test-c: c-lib @echo -e "${BLUE}Running C tests...${NC}" @cd $(BUILD_DIR) && ctest $(if $(filter 1,$(VERBOSE)),-V,) -.PHONY: test-rust -test-rust: - @echo -e "${BLUE}Running Rust tests...${NC}" - @$(CARGO) test $(if $(filter 0,$(DEBUG)),--release,) - -# Benchmark targets -.PHONY: bench -bench: - @echo -e "${BLUE}Running benchmarks...${NC}" - @$(CARGO) bench - -# Documentation targets -.PHONY: docs -docs: -ifeq ($(BUILD_DOCS), 1) - @echo -e "${BLUE}Building documentation...${NC}" - @$(CARGO) doc --no-deps - @echo -e "${GREEN}Documentation built in target/doc/bitcoinpqc/index.html${NC}" -else - @echo -e "${YELLOW}Skipping documentation build (use BUILD_DOCS=1 to enable)${NC}" -endif - -# Language bindings -.PHONY: python -python: rust-lib - @echo -e "${BLUE}Building Python bindings...${NC}" - @if [ -n "$(PYTHON)" ]; then \ - echo -e "${YELLOW}Creating a Python virtual environment...${NC}"; \ - $(PYTHON) -m venv python/.venv || { echo -e "${RED}Failed to create virtual environment${NC}"; exit 1; }; \ - echo -e "${GREEN}Virtual environment created at python/.venv${NC}"; \ - echo -e "${YELLOW}Installing Python bindings in virtual environment...${NC}"; \ - . python/.venv/bin/activate && cd python && $(PYTHON) -m pip install -e . && \ - echo -e "${GREEN}Python bindings installed successfully in virtual environment${NC}"; \ - echo -e "${YELLOW}To use the bindings, activate the virtual environment:${NC}"; \ - echo -e " source python/.venv/bin/activate"; \ - else \ - echo -e "${RED}Python not found, skipping Python bindings${NC}"; \ - fi - -.PHONY: nodejs -nodejs: rust-lib - @echo -e "${BLUE}Building NodeJS bindings...${NC}" - @if [ -n "$(NPM)" ]; then \ - cd nodejs && $(NPM) install && $(NPM) run build; \ - else \ - echo -e "${RED}NPM not found, skipping NodeJS bindings${NC}"; \ - fi - # Installation targets .PHONY: install -install: install-c install-rust - -.PHONY: install-c -install-c: c-lib +install: c-lib @echo -e "${BLUE}Installing C library to $(PREFIX)...${NC}" @cd $(BUILD_DIR) && cmake --install . -.PHONY: install-rust -install-rust: rust-lib - @echo -e "${BLUE}Installing Rust library...${NC}" - @$(CARGO) install --path . - # Clean targets .PHONY: clean -clean: clean-c clean-rust clean-bindings - -.PHONY: clean-c -clean-c: - @echo -e "${BLUE}Cleaning C library build files...${NC}" +clean: + @echo -e "${BLUE}Cleaning build files...${NC}" @rm -rf $(BUILD_DIR) -.PHONY: clean-rust -clean-rust: - @echo -e "${BLUE}Cleaning Rust library build files...${NC}" - @$(CARGO) clean - -.PHONY: clean-bindings -clean-bindings: - @echo -e "${BLUE}Cleaning language bindings...${NC}" - @if [ -d "python/build" ]; then rm -rf python/build; fi - @if [ -d "nodejs/dist" ]; then rm -rf nodejs/dist; fi - # Help target .PHONY: help help: @echo -e "${BLUE}libbitcoinpqc Makefile Help${NC}" @echo -e "${BLUE}-------------------------${NC}" @echo -e "Main targets:" - @echo -e " ${GREEN}all${NC} - Build C and Rust libraries and language bindings (default)" - @echo -e " ${GREEN}bindings${NC} - Build Python and NodeJS bindings" + @echo -e " ${GREEN}all${NC} - Build the C library (default)" @echo -e " ${GREEN}everything${NC} - Build all components including examples and tests" - @echo -e " ${GREEN}c-lib${NC} - Build only the C library" - @echo -e " ${GREEN}rust-lib${NC} - Build only the Rust library" - @echo -e " ${GREEN}python${NC} - Build Python bindings" - @echo -e " ${GREEN}nodejs${NC} - Build NodeJS bindings" + @echo -e " ${GREEN}c-lib${NC} - Build the C library" @echo -e " ${GREEN}examples${NC} - Build example programs" @echo -e " ${GREEN}tests${NC} - Run all tests" - @echo -e " ${GREEN}bench${NC} - Run benchmarks" - @echo -e " ${GREEN}docs${NC} - Build documentation" - @echo -e " ${GREEN}install${NC} - Install libraries" + @echo -e " ${GREEN}install${NC} - Install the library" @echo -e " ${GREEN}clean${NC} - Clean all build files" @echo -e " ${GREEN}help${NC} - Display this help message" @echo -e " ${GREEN}fix-warnings${NC} - Fix common build warnings" @@ -218,8 +110,8 @@ help: @echo -e "" @echo -e "Developer targets:" @echo -e " ${GREEN}dev${NC} - Run format, lint, and analyze" - @echo -e " ${GREEN}format${NC} - Format C and Rust code" - @echo -e " ${GREEN}lint${NC} - Lint C and Rust code" + @echo -e " ${GREEN}format${NC} - Format C code" + @echo -e " ${GREEN}lint${NC} - Lint C code" @echo -e " ${GREEN}analyze${NC} - Run static analysis on C code" @echo -e " ${GREEN}dev-deps${NC} - Install development dependencies" @echo -e "" @@ -227,7 +119,6 @@ help: @echo -e " ${YELLOW}DEBUG=1${NC} - Build in debug mode (default: 0)" @echo -e " ${YELLOW}VERBOSE=1${NC} - Show verbose build output (default: 0)" @echo -e " ${YELLOW}PREFIX=/path${NC} - Installation prefix (default: /usr/local)" - @echo -e " ${YELLOW}BUILD_DOCS=1${NC} - Build documentation (default: 0)" @echo -e " ${YELLOW}NO_COLOR=1${NC} - Disable colored output (default: 0)" # Fix warnings targets @@ -255,12 +146,6 @@ troubleshoot: @echo -e " ${YELLOW}Missing tools:${NC}" @echo -e " Make sure you have all required development tools installed." @echo -e "" - @echo -e " ${YELLOW}Python or NodeJS bindings issues:${NC}" - @echo -e " If you experience Python or NodeJS binding problems:" - @echo -e " - For Python: Check the virtual environment at python/.venv" - @echo -e " - For NodeJS: Check the build logs in nodejs/build" - @echo -e " You can build bindings separately with 'make python' or 'make nodejs'" - @echo -e "" @echo -e " ${YELLOW}Terminal color issues:${NC}" @echo -e " If you see raw escape sequences (like \\033[0;32m), run with NO_COLOR=1" @echo -e "" @@ -276,15 +161,9 @@ format: @echo -e "${BLUE}Formatting code...${NC}" @if command -v clang-format > /dev/null; then \ find src include examples -name "*.c" -o -name "*.h" | xargs clang-format -i -style=file; \ - echo -e "${GREEN}C/C++ code formatted${NC}"; \ - else \ - echo -e "${YELLOW}clang-format not found, skipping C/C++ formatting${NC}"; \ - fi - @if [ -n "$(CARGO)" ]; then \ - $(CARGO) fmt; \ - echo -e "${GREEN}Rust code formatted${NC}"; \ + echo -e "${GREEN}C code formatted${NC}"; \ else \ - echo -e "${YELLOW}Cargo not found, skipping Rust formatting${NC}"; \ + echo -e "${YELLOW}clang-format not found, skipping C formatting${NC}"; \ fi .PHONY: lint @@ -292,15 +171,9 @@ lint: @echo -e "${BLUE}Linting code...${NC}" @if command -v cppcheck > /dev/null; then \ cppcheck --enable=all --suppressions-list=.cppcheck-suppressions --error-exitcode=0 src include examples; \ - echo -e "${GREEN}C/C++ code linted${NC}"; \ + echo -e "${GREEN}C code linted${NC}"; \ else \ - echo -e "${YELLOW}cppcheck not found, skipping C/C++ linting${NC}"; \ - fi - @if [ -n "$(CARGO)" ]; then \ - $(CARGO) clippy; \ - echo -e "${GREEN}Rust code linted${NC}"; \ - else \ - echo -e "${YELLOW}Cargo not found, skipping Rust linting${NC}"; \ + echo -e "${YELLOW}cppcheck not found, skipping C linting${NC}"; \ fi .PHONY: analyze @@ -330,7 +203,3 @@ dev-deps: echo "- cppcheck (for static analysis)"; \ echo "- clang tools (for static analysis)"; \ fi - @if [ -n "$(CARGO)" ]; then \ - rustup component add clippy rustfmt; \ - echo -e "${GREEN}Rust development tools installed${NC}"; \ - fi diff --git a/README.md b/README.md index d49d7f6..47a8835 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # libbitcoinpqc -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: +A C library 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. @@ -14,9 +14,6 @@ This library serves as the cryptographic foundation for the Bitcoin QuBit soft f ## Features - Clean, unified C API for all three signature algorithms -- Safe Rust bindings with memory safety and zero-copy operations -- NodeJS TypeScript bindings with full type safety -- Python bindings for easy integration - User-provided entropy (bring your own randomness) - Key generation, signing, and verification functions - Minimal dependencies @@ -29,8 +26,6 @@ This library serves as the cryptographic foundation for the Bitcoin QuBit soft f | 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 | -See [REPORT.md](benches/REPORT.md) for performance and size comparison to secp256k1. - ## Security Notes - This library does not provide its own random number generation. It is essential that the user provide entropy from a cryptographically secure source. @@ -59,7 +54,6 @@ Cryptographic dependencies included in this project: - CMake 3.10 or higher - C99 compiler -- Rust 1.50 or higher (for Rust bindings) ### Building @@ -73,46 +67,8 @@ mkdir build cd build cmake .. make - -# Build the Rust library and bindings -cd .. -cargo build --release -``` - -## Fuzz Testing - -This library includes fuzz testing targets using [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz). - -### Prerequisites - -```bash -# Install cargo-fuzz -cargo install cargo-fuzz -``` - -### Available Fuzz Targets - -1. **keypair_generation** - Tests key pair generation with different algorithms -2. **sign_verify** - Tests signature creation and verification -3. **cross_algorithm** - Tests verification with mismatched keys and signatures from different algorithms - -### Running Fuzz Tests - -```bash -# Run a specific fuzz target -cargo fuzz run keypair_generation -cargo fuzz run sign_verify -cargo fuzz run cross_algorithm - -# Run a fuzz target for a specific amount of time (in seconds) -cargo fuzz run keypair_generation -- -max_total_time=60 - -# Run a fuzz target with a specific number of iterations -cargo fuzz run sign_verify -- -runs=1000000 ``` -See `fuzz/README.md` for more details on fuzz testing. - ## C API Usage ```c @@ -143,170 +99,6 @@ bitcoin_pqc_signature_free(&signature); bitcoin_pqc_keypair_free(&keypair); ``` -## Rust API Usage - -Rust docs can be found on [docs.rs](https://docs.rs/bitcoinpqc/latest/bitcoinpqc/). - -```rust -use bitcoinpqc::{Algorithm, generate_keypair, sign, verify}; -use rand::{RngCore, rngs::OsRng}; - -// Generate random data for key generation -let mut random_data = vec![0u8; 128]; -OsRng.fill_bytes(&mut random_data); - -// Generate a key pair -let keypair = generate_keypair(Algorithm::MLDSA44, &random_data).unwrap(); - -// Create a message to sign -let message = b"Message to sign"; - -// Sign the message deterministically -let signature = sign(&keypair.secret_key, message).unwrap(); - -// Verify the signature -verify(&keypair.public_key, message, &signature).unwrap(); -``` - -## Python API Usage - -[Python bindings are also available for libbitcoinpqc](https://pypi.org/project/bitcoinpqc/0.1.0/), allowing you to use the post-quantum cryptographic algorithms from Python code. - -### Installation - -```bash -# Install the Python package -cd python -pip install -e . -``` - -### Prerequisites - -- Python 3.7 or higher -- The libbitcoinpqc C library must be built and installed - -### Example Usage - -```python -import secrets -from bitcoinpqc import Algorithm, keygen, sign, verify - -# Generate random data for key generation -random_data = secrets.token_bytes(128) - -# Generate a key pair -algorithm = Algorithm.ML_DSA_44 # CRYSTALS-Dilithium -keypair = keygen(algorithm, random_data) - -# Create a message to sign -message = b"Hello, Bitcoin PQC!" - -# Sign the message -signature = sign(algorithm, keypair.secret_key, message) - -# Verify the signature -is_valid = verify(algorithm, keypair.public_key, message, signature) -print(f"Signature valid: {is_valid}") # Should print True - -# Verification with incorrect message will fail -bad_message = b"Tampered message!" -is_valid = verify(algorithm, keypair.public_key, bad_message, signature) -print(f"Signature valid: {is_valid}") # Should print False -``` - -### Python API Reference - -The Python API mirrors the C API closely, with some Pythonic improvements: - -- **Algorithm** - Enum class for algorithm selection - - `SECP256K1_SCHNORR` - - `ML_DSA_44` (CRYSTALS-Dilithium) - - `SLH_DSA_SHAKE_128S` (SPHINCS+) - -- **KeyPair** - Class to hold a public/secret key pair - - `algorithm` - The algorithm used - - `public_key` - The public key as bytes - - `secret_key` - The secret key as bytes - -- **Signature** - Class to hold a signature - - `algorithm` - The algorithm used - - `signature` - The signature as bytes - -- **Functions** - - `public_key_size(algorithm)` - Get the public key size for an algorithm - - `secret_key_size(algorithm)` - Get the secret key size for an algorithm - - `signature_size(algorithm)` - Get the signature size for an algorithm - - `keygen(algorithm, random_data)` - Generate a key pair - - `sign(algorithm, secret_key, message)` - Sign a message - - `verify(algorithm, public_key, message, signature)` - Verify a signature - -## NodeJS TypeScript API Usage - -[NodeJS TypeScript bindings](https://www.npmjs.com/package/bitcoinpqc) allow you to use post-quantum cryptographic algorithms in JavaScript/TypeScript projects. - -### Installation - -```bash -# Install the Node.js package -npm install bitcoinpqc -``` - -### Prerequisites - -- Node.js 16 or higher -- The libbitcoinpqc C library must be built and installed - -### Example Usage - -```typescript -import { Algorithm, generateKeyPair, sign, verify } from 'bitcoinpqc'; -import crypto from 'crypto'; - -// Generate random data for key generation -const randomData = crypto.randomBytes(128); - -// Generate a key pair using ML-DSA-44 (CRYSTALS-Dilithium) -const keypair = generateKeyPair(Algorithm.ML_DSA_44, randomData); - -// Create a message to sign -const message = Buffer.from('Message to sign'); - -// Sign the message deterministically -const signature = sign(keypair.secretKey, message); - -// Verify the signature -verify(keypair.publicKey, message, signature); -// If verification fails, it will throw a PqcError - -// You can also verify using the raw signature bytes -verify(keypair.publicKey, message, signature.bytes); -``` - -### NodeJS TypeScript API Reference - -The TypeScript API provides a clean, modern interface: - -- **Algorithm** - Enum for algorithm selection - - `SECP256K1_SCHNORR` - - `ML_DSA_44` (CRYSTALS-Dilithium) - - `SLH_DSA_SHAKE_128S` (SPHINCS+) - -- **Classes** - - `PublicKey` - Public key wrapper - - `SecretKey` - Secret key wrapper with secure handling - - `KeyPair` - Container for public/secret key pairs - - `Signature` - Signature wrapper - -- **Functions** - - `publicKeySize(algorithm)` - Get the public key size for an algorithm - - `secretKeySize(algorithm)` - Get the secret key size for an algorithm - - `signatureSize(algorithm)` - Get the signature size for an algorithm - - `generateKeyPair(algorithm, randomData)` - Generate a key pair - - `sign(secretKey, message)` - Sign a message - - `verify(publicKey, message, signature)` - Verify a signature - -For more details, see the [NodeJS TypeScript bindings README](nodejs/README.md). - ## Acknowledgments - The original NIST PQC competition teams for their reference implementations diff --git a/benches/README.md b/benches/README.md deleted file mode 100644 index e6decfd..0000000 --- a/benches/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# Post-Quantum Cryptography Benchmarks - -This directory contains benchmarks for the post-quantum cryptography algorithms implemented in the library, as well as benchmarks for secp256k1 for comparison. - -## Running All Benchmarks - -To run all benchmarks: - -``` -cargo bench -``` - -## Running Algorithm-Specific Benchmarks - -You can run benchmarks for a specific algorithm by using the filter option with `cargo bench`: - -### ML-DSA-44 (CRYSTALS-Dilithium) - -``` -cargo bench -- ml_dsa_44 -``` - -### SLH-DSA-128S (SPHINCS+) - -``` -cargo bench -- slh_dsa_128s -``` - -### secp256k1 (for comparison) - -``` -cargo bench -- secp256k1 -``` - -## Running Operation-Specific Benchmarks - -You can also run benchmarks for specific operations: - -### Key Generation Benchmarks - -``` -cargo bench -- keygen -``` - -### Signing Benchmarks - -``` -cargo bench -- signing -``` - -### Verification Benchmarks - -``` -cargo bench -- verification -``` - -### Size Comparison Benchmarks - -``` -cargo bench -- sizes -``` - -## Comparing Algorithms - -To see how post-quantum algorithms compare to current standards: - -``` -# Compare key generation speed -cargo bench -- keygen - -# Compare signing speed -cargo bench -- signing - -# Compare verification speed -cargo bench -- verification - -# Compare key and signature sizes -cargo bench -- sizes -``` - -## Troubleshooting - -If you encounter any issues with a specific algorithm, try running only that algorithm's benchmarks: - -``` -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 deleted file mode 100644 index e8538ee..0000000 --- a/benches/REPORT.md +++ /dev/null @@ -1,31 +0,0 @@ -# Benchmark Report: Post-Quantum Cryptography vs secp256k1 - -This report compares the performance and size characteristics of post-quantum cryptographic algorithms with secp256k1. - -## Performance Comparison - -All values show relative performance compared to secp256k1 (lower is better). - -| Algorithm | Key Generation | Signing | Verification | -|-----------|----------------|---------|--------------| -| secp256k1 | 1.00x | 1.00x | 1.00x | -| ML-DSA-44 | *Needs Update* | *Needs Update* | *Needs Update* | -| SLH-DSA-128S | *Needs Update* | *Needs Update* | *Needs Update* | - -*Note: Performance values require parsing Criterion output and are not yet updated automatically.* - -## Size Comparison - -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) | -| 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) | - -## Summary - -This benchmark comparison demonstrates the performance and size tradeoffs between post-quantum cryptographic algorithms and traditional elliptic curve cryptography (secp256k1). - -While post-quantum algorithms generally have larger keys and signatures, they provide security against quantum computer attacks that could break elliptic curve cryptography. diff --git a/benches/sig_benchmarks.rs b/benches/sig_benchmarks.rs deleted file mode 100644 index 796bdbb..0000000 --- a/benches/sig_benchmarks.rs +++ /dev/null @@ -1,479 +0,0 @@ -use std::collections::HashMap; -use std::fs::{File, OpenOptions}; -use std::io::{Read, Write}; -use std::sync::Mutex; -use std::sync::OnceLock; -use std::time::Duration; - -use criterion::{criterion_group, criterion_main, Criterion}; -use rand::{rng, RngCore}; - -use bitcoinpqc::{generate_keypair, sign, verify, Algorithm}; - -// Set to true to enable debug output, false to disable -const DEBUG_MODE: bool = false; - -// Global storage for sizes -static SIZE_RESULTS: OnceLock>> = OnceLock::new(); - -// Helper function to get or initialize the size results -fn get_size_results() -> &'static Mutex> { - SIZE_RESULTS.get_or_init(|| Mutex::new(HashMap::new())) -} - -// Conditional debug print macro -macro_rules! debug_println { - ($($arg:tt)*) => { - if DEBUG_MODE { - println!($($arg)*); - } - }; -} - -// Get random data of a specified size -fn get_random_data(size: usize) -> Vec { - let mut random_data = vec![0u8; size]; - rng().fill_bytes(&mut random_data); - random_data -} - -// Configure benchmark group with common settings -fn configure_group(group: &mut criterion::BenchmarkGroup) { - group.measurement_time(Duration::from_secs(10)); -} - -// Helper function to store size results -fn store_size_result(name: &str, value: usize) { - let results = get_size_results(); - let mut results = results.lock().unwrap(); - results.insert(name.to_string(), value); -} - -// ML-DSA-44 BENCHMARKS - -fn bench_ml_dsa_44_keygen(c: &mut Criterion) { - let mut group = c.benchmark_group("ml_dsa_keygen"); - configure_group(&mut group); - - group.bench_function("ML_DSA_44", |b| { - b.iter(|| { - let random_data = get_random_data(256); - generate_keypair(Algorithm::ML_DSA_44, &random_data).unwrap() - }); - }); - - group.finish(); -} - -fn bench_ml_dsa_44_signing(c: &mut Criterion) { - let mut group = c.benchmark_group("ml_dsa_signing"); - configure_group(&mut group); - - let message = b"This is a test message for benchmarking"; - let random_data = get_random_data(256); - let ml_keypair = generate_keypair(Algorithm::ML_DSA_44, &random_data).unwrap(); - - group.bench_function("ML_DSA_44", |b| { - b.iter(|| sign(&ml_keypair.secret_key, message)); - }); - - group.finish(); -} - -fn bench_ml_dsa_44_verification(c: &mut Criterion) { - let mut group = c.benchmark_group("ml_dsa_verification"); - configure_group(&mut group); - - let message = b"This is a test message for benchmarking"; - let random_data = get_random_data(256); - let ml_keypair = generate_keypair(Algorithm::ML_DSA_44, &random_data).unwrap(); - let ml_sig = sign(&ml_keypair.secret_key, message).unwrap(); - - group.bench_function("ML_DSA_44", |b| { - b.iter(|| verify(&ml_keypair.public_key, message, &ml_sig).unwrap()); - }); - - group.finish(); -} - -// SLH-DSA-128S BENCHMARKS - -fn bench_slh_dsa_128s_keygen(c: &mut Criterion) { - let mut group = c.benchmark_group("slh_dsa_keygen"); - configure_group(&mut group); - group.sample_size(10); // Reduce sample count for SLH-DSA which is slower - - group.bench_function("SLH_DSA_128S", |b| { - b.iter(|| { - let random_data = get_random_data(256); - generate_keypair(Algorithm::SLH_DSA_128S, &random_data).unwrap() - }); - }); - - group.finish(); -} - -fn bench_slh_dsa_128s_signing(c: &mut Criterion) { - let mut group = c.benchmark_group("slh_dsa_signing"); - configure_group(&mut group); - group.sample_size(10); // Reduce sample count for SLH-DSA which is slower - - let message = b"This is a test message for benchmarking"; - let random_data = get_random_data(256); - let slh_keypair = generate_keypair(Algorithm::SLH_DSA_128S, &random_data).unwrap(); - - group.bench_function("SLH_DSA_128S", |b| { - b.iter(|| sign(&slh_keypair.secret_key, message)); - }); - - group.finish(); -} - -fn bench_slh_dsa_128s_verification(c: &mut Criterion) { - let mut group = c.benchmark_group("slh_dsa_verification"); - configure_group(&mut group); - group.sample_size(10); // Reduce sample count for SLH-DSA which is slower - - let message = b"This is a test message for benchmarking"; - let random_data = get_random_data(256); - let slh_keypair = generate_keypair(Algorithm::SLH_DSA_128S, &random_data).unwrap(); - let slh_sig = sign(&slh_keypair.secret_key, message).unwrap(); - - group.bench_function("SLH_DSA_128S", |b| { - b.iter(|| verify(&slh_keypair.public_key, message, &slh_sig).unwrap()); - }); - - group.finish(); -} - -// SIZE REPORTING - Combined in one benchmark - -fn bench_sizes(c: &mut Criterion) { - let group = c.benchmark_group("sizes"); - - let message = b"This is a test message for benchmarking"; - - // ML-DSA-44 - let random_data = get_random_data(256); - let ml_keypair = generate_keypair(Algorithm::ML_DSA_44, &random_data).unwrap(); - let ml_sig = sign(&ml_keypair.secret_key, message).unwrap(); - let ml_pk_size = ml_keypair.public_key.bytes.len(); - let ml_sk_size = ml_keypair.secret_key.bytes.len(); - let ml_sig_size = ml_sig.bytes.len(); - let ml_pk_sig_size = ml_pk_size + ml_sig_size; - - // Store size results - store_size_result("ml_dsa_44_pubkey", ml_pk_size); - store_size_result("ml_dsa_44_seckey", ml_sk_size); - store_size_result("ml_dsa_44_sig", ml_sig_size); - store_size_result("ml_dsa_44_pk_sig", ml_pk_sig_size); - - // SLH-DSA-128S - let random_data = get_random_data(256); - let slh_keypair = generate_keypair(Algorithm::SLH_DSA_128S, &random_data).unwrap(); - let slh_sig = sign(&slh_keypair.secret_key, message).unwrap(); - let slh_pk_size = slh_keypair.public_key.bytes.len(); - let slh_sk_size = slh_keypair.secret_key.bytes.len(); - let slh_sig_size = slh_sig.bytes.len(); - let slh_pk_sig_size = slh_pk_size + slh_sig_size; - - // Store size results - store_size_result("slh_dsa_128s_pubkey", slh_pk_size); - store_size_result("slh_dsa_128s_seckey", slh_sk_size); - store_size_result("slh_dsa_128s_sig", slh_sig_size); - store_size_result("slh_dsa_128s_pk_sig", slh_pk_sig_size); - - // Print key and signature sizes - debug_println!("Key and Signature Sizes (bytes):"); - debug_println!("ML-DSA-44:"); - debug_println!( - " Public key: {}, Secret key: {}, Signature: {}", - ml_pk_size, - ml_sk_size, - ml_sig_size - ); - - debug_println!("SLH-DSA-128S:"); - debug_println!( - " Public key: {}, Secret key: {}, Signature: {}", - slh_pk_size, - slh_sk_size, - slh_sig_size - ); - - group.finish(); -} - -// Function to generate the markdown report by updating existing file -fn generate_report(_c: &mut Criterion) { - let report_path = "benches/REPORT.md"; - let mut report_content = String::new(); - - // Try to read the existing report file - match File::open(report_path) { - Ok(mut file) => { - if file.read_to_string(&mut report_content).is_err() { - eprintln!( - "Error reading existing report file: {}. Creating a new one.", - report_path - ); - report_content.clear(); - } - } - Err(_) => { - println!("Report file {} not found. Creating a new one.", report_path); - } - } - - // Get size results - let size_results = get_size_results(); - let size_results = size_results.lock().unwrap(); - - // --- Parse existing secp256k1 values or use defaults --- - let mut secp_pubkey_size = 32; // Default - let mut secp_seckey_size = 32; // Default - let mut secp_sig_size = 64; // Default - let mut secp_pk_sig_size = secp_pubkey_size + secp_sig_size; // Default derived - - // Find and parse secp256k1 sizes from the report if available - if let Some(line) = report_content - .lines() - .find(|l| l.starts_with("| secp256k1 |")) - { - let parts: Vec<&str> = line.split('|').map(|s| s.trim()).collect(); - // Expecting format: | secp256k1 | SK bytes (rel) | PK bytes (rel) | Sig bytes (rel) | PK+Sig bytes (rel) | - if parts.len() > 5 { - // Parse Secret Key Size (Column 2) - if let Ok(sk) = parts[2] - .split_whitespace() - .next() - .unwrap_or("0") - .parse::() - { - secp_seckey_size = sk; - } - // Parse Public Key Size (Column 3) - if let Ok(pk) = parts[3] - .split_whitespace() - .next() - .unwrap_or("0") - .parse::() - { - secp_pubkey_size = pk; - } - // Parse Signature Size (Column 4) - if let Ok(sig) = parts[4] - .split_whitespace() - .next() - .unwrap_or("0") - .parse::() - { - secp_sig_size = sig; - } - // Recalculate combined size based on parsed values (Column 5 is derived) - secp_pk_sig_size = secp_pubkey_size + secp_sig_size; - } else { - println!( - "Warning: Found secp256k1 line but failed to parse sizes correctly from: {}", - line - ); - } - } - - // --- Process lines and update size table --- - let mut updated_lines = Vec::new(); - let mut in_size_table = false; - let mut size_table_header_found = false; - // Define the expected header and separator for the size table (matching the commit diff) - let size_table_header = - "| Algorithm | Secret Key | Public Key | Signature | Public Key + Signature |"; - let size_table_separator = - "|-----------|------------|------------|-----------|------------------------|"; - - for line in report_content.lines() { - let mut line_to_push = line.to_string(); // Default to original line - let trimmed_line = line.trim(); - - // Detect entering/leaving the size table - if trimmed_line == size_table_separator && size_table_header_found { - in_size_table = true; // Mark start of data rows - } else if trimmed_line == size_table_header { - size_table_header_found = true; // Found the header - } else if trimmed_line.is_empty() || trimmed_line.starts_with("#") { - // Stop processing table rows if we hit an empty line or a new section header - if in_size_table { - in_size_table = false; - size_table_header_found = false; // Reset for potential future tables - } - } - - // Update rows within the size table - if in_size_table { - if trimmed_line.starts_with("| secp256k1 |") { - // Format the secp256k1 line using parsed/default values - line_to_push = format!( - "| 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("| 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); - let ml_sig_size = size_results.get("ml_dsa_44_sig").cloned().unwrap_or(0); - let ml_pk_sig_size = size_results.get("ml_dsa_44_pk_sig").cloned().unwrap_or(0); - line_to_push = format!( - "| ML-DSA-44 | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) |", - ml_seckey_size, if secp_seckey_size > 0 { ml_seckey_size as f64 / secp_seckey_size as f64 } else { 0.0 }, - ml_pubkey_size, if secp_pubkey_size > 0 { ml_pubkey_size as f64 / secp_pubkey_size as f64 } else { 0.0 }, - ml_sig_size, if secp_sig_size > 0 { ml_sig_size as f64 / secp_sig_size as f64 } else { 0.0 }, - ml_pk_sig_size, if secp_pk_sig_size > 0 { ml_pk_sig_size as f64 / secp_pk_sig_size as f64 } else { 0.0 } - ); - } else if trimmed_line.starts_with("| SLH-DSA-128S |") { - let slh_pubkey_size = size_results - .get("slh_dsa_128s_pubkey") - .cloned() - .unwrap_or(0); - let slh_seckey_size = size_results - .get("slh_dsa_128s_seckey") - .cloned() - .unwrap_or(0); - let slh_sig_size = size_results.get("slh_dsa_128s_sig").cloned().unwrap_or(0); - let slh_pk_sig_size = size_results - .get("slh_dsa_128s_pk_sig") - .cloned() - .unwrap_or(0); - line_to_push = format!( - "| SLH-DSA-128S | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) |", - slh_seckey_size, if secp_seckey_size > 0 { slh_seckey_size as f64 / secp_seckey_size as f64 } else { 0.0 }, - slh_pubkey_size, if secp_pubkey_size > 0 { slh_pubkey_size as f64 / secp_pubkey_size as f64 } else { 0.0 }, - slh_sig_size, if secp_sig_size > 0 { slh_sig_size as f64 / secp_sig_size as f64 } else { 0.0 }, - slh_pk_sig_size, if secp_pk_sig_size > 0 { slh_pk_sig_size as f64 / secp_pk_sig_size as f64 } else { 0.0 } - ); - } - // Note: Any other lines within the size table block will keep their original content (e.g., comments) - } - - updated_lines.push(line_to_push); - } - - // --- Generate default report if needed --- - // If the report was empty or didn't contain the expected size table header, generate a default one. - if report_content.is_empty() || !report_content.contains(size_table_header) { - println!("Generating default report structure in {}.", report_path); - updated_lines.clear(); // Start fresh - - // Default Header - updated_lines - .push("# Benchmark Report: Post-Quantum Cryptography vs secp256k1".to_string()); - updated_lines.push("\nThis report compares the performance and size characteristics of post-quantum cryptographic algorithms with secp256k1.\n".to_string()); - - // Default Performance section (with placeholders) - updated_lines.push("## Performance Comparison\n".to_string()); - updated_lines.push( - "All values show relative performance compared to secp256k1 (lower is better).\n" - .to_string(), - ); - 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("| ML-DSA-44 | *Needs Update* | *Needs Update* | *Needs Update* |".to_string()); // Placeholders - updated_lines.push( - "| SLH-DSA-128S | *Needs Update* | *Needs Update* | *Needs Update* |".to_string(), - ); // Placeholders - updated_lines.push("\n*Note: Performance values require parsing Criterion output and are not yet updated automatically.*".to_string()); - - // Default Size section (using current data and new format) - updated_lines.push("\n## Size Comparison\n".to_string()); - updated_lines.push( - "All values show actual sizes with relative comparison to secp256k1.\n".to_string(), - ); - updated_lines.push(size_table_header.to_string()); // Use the defined header - updated_lines.push(size_table_separator.to_string()); // Use the defined separator - - // secp line - updated_lines.push(format!( - "| 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 - )); - - // 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); - let ml_sig_size = size_results.get("ml_dsa_44_sig").cloned().unwrap_or(0); - let ml_pk_sig_size = size_results.get("ml_dsa_44_pk_sig").cloned().unwrap_or(0); - updated_lines.push(format!( - "| ML-DSA-44 | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) |", - ml_seckey_size, if secp_seckey_size > 0 { ml_seckey_size as f64 / secp_seckey_size as f64 } else { 0.0 }, - ml_pubkey_size, if secp_pubkey_size > 0 { ml_pubkey_size as f64 / secp_pubkey_size as f64 } else { 0.0 }, - ml_sig_size, if secp_sig_size > 0 { ml_sig_size as f64 / secp_sig_size as f64 } else { 0.0 }, - ml_pk_sig_size, if secp_pk_sig_size > 0 { ml_pk_sig_size as f64 / secp_pk_sig_size as f64 } else { 0.0 } - )); - - // SLH-DSA line - let slh_pubkey_size = size_results - .get("slh_dsa_128s_pubkey") - .cloned() - .unwrap_or(0); - let slh_seckey_size = size_results - .get("slh_dsa_128s_seckey") - .cloned() - .unwrap_or(0); - let slh_sig_size = size_results.get("slh_dsa_128s_sig").cloned().unwrap_or(0); - let slh_pk_sig_size = size_results - .get("slh_dsa_128s_pk_sig") - .cloned() - .unwrap_or(0); - updated_lines.push(format!( - "| SLH-DSA-128S | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) |", - slh_seckey_size, if secp_seckey_size > 0 { slh_seckey_size as f64 / secp_seckey_size as f64 } else { 0.0 }, - slh_pubkey_size, if secp_pubkey_size > 0 { slh_pubkey_size as f64 / secp_pubkey_size as f64 } else { 0.0 }, - slh_sig_size, if secp_sig_size > 0 { slh_sig_size as f64 / secp_sig_size as f64 } else { 0.0 }, - slh_pk_sig_size, if secp_pk_sig_size > 0 { slh_pk_sig_size as f64 / secp_pk_sig_size as f64 } else { 0.0 } - )); - - // Default Summary - updated_lines.push("\n## Summary\n".to_string()); - updated_lines.push("This benchmark comparison demonstrates the performance and size tradeoffs between post-quantum cryptographic algorithms and traditional elliptic curve cryptography (secp256k1).".to_string()); - updated_lines.push("\nWhile post-quantum algorithms generally have larger keys and signatures, they provide security against quantum computer attacks that could break elliptic curve cryptography.".to_string()); - } - - // --- Write updated content back to file --- - match OpenOptions::new() - .write(true) - .create(true) - .truncate(true) - .open(report_path) - { - Ok(mut file) => { - let output_string = updated_lines.join("\n"); - if file.write_all(output_string.as_bytes()).is_err() { - eprintln!("Error writing updated report to {}", report_path); - } else { - // Add a trailing newline if the content doesn't end with one - if !output_string.ends_with('\n') { - if file.write_all(b"\n").is_err() { - eprintln!("Error writing trailing newline to {}", report_path); - } - } - println!("Report updated successfully: {}", report_path); - } - } - Err(e) => { - eprintln!("Failed to open {} for writing: {}", report_path, e); - } - } -} - -// Organize the benchmarks by algorithm rather than by operation -criterion_group!( - benches, - bench_ml_dsa_44_keygen, - bench_ml_dsa_44_signing, - bench_ml_dsa_44_verification, - bench_slh_dsa_128s_keygen, - bench_slh_dsa_128s_signing, - bench_slh_dsa_128s_verification, - bench_sizes, - generate_report -); -criterion_main!(benches); diff --git a/build.rs b/build.rs deleted file mode 100644 index eb5e25a..0000000 --- a/build.rs +++ /dev/null @@ -1,40 +0,0 @@ -use std::env; -use std::path::PathBuf; - -fn main() { - // Build the C library - let dst = cmake::build("."); - - // Link against the built library - println!("cargo:rustc-link-search=native={}/lib", dst.display()); - println!("cargo:rustc-link-lib=static=bitcoinpqc"); - - // Tell cargo to invalidate the built crate whenever the headers change - 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"); - - // The bindgen::Builder is the main entry point to bindgen - let bindings = bindgen::Builder::default() - // The input header to generate bindings for - .header("include/libbitcoinpqc/bitcoinpqc.h") - // Tell bindgen to generate constants for enums - .bitfield_enum("bitcoin_pqc_algorithm_t") - .bitfield_enum("bitcoin_pqc_error_t") - // Tell cargo to invalidate the built crate whenever the wrapper changes - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) - // Suppress warnings for unused code in the generated bindings - .allowlist_function("bitcoin_pqc_.*") - .allowlist_type("bitcoin_pqc_.*") - .allowlist_var("BITCOIN_PQC_.*") - // Generate bindings - .generate() - // Unwrap the Result and panic on failure - .expect("Unable to generate bindings"); - - // Write the bindings to the $OUT_DIR/bindings.rs file - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); -} diff --git a/examples/basic.rs b/examples/basic.rs deleted file mode 100644 index 2305e45..0000000 --- a/examples/basic.rs +++ /dev/null @@ -1,77 +0,0 @@ -use bitcoinpqc::{generate_keypair, sign, verify, Algorithm}; -use rand::{rng, RngCore}; -use std::time::Instant; - -fn main() { - println!("Bitcoin PQC Library Example"); - println!("==========================\n"); - println!("This example tests the post-quantum signature algorithms designed for BIP-360 and the Bitcoin QuBit soft fork.\n"); - - // Generate random data for key generation - let mut random_data = vec![0u8; 128]; - rng().fill_bytes(&mut random_data); - - // 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); -} - -fn test_algorithm(algorithm: Algorithm, name: &str, random_data: &[u8]) { - println!("Testing {name} algorithm:"); - println!("------------------------"); - - // Get key and signature sizes - let pk_size = bitcoinpqc::public_key_size(algorithm); - let sk_size = bitcoinpqc::secret_key_size(algorithm); - let sig_size = bitcoinpqc::signature_size(algorithm); - - println!("Public key size: {pk_size} bytes"); - println!("Secret key size: {sk_size} bytes"); - println!("Signature size: {sig_size} bytes"); - - // Generate a key pair - let start = Instant::now(); - let keypair = match generate_keypair(algorithm, random_data) { - Ok(kp) => kp, - Err(e) => { - println!("Error generating key pair: {e}"); - return; - } - }; - let duration = start.elapsed(); - println!("Key generation time: {duration:?}"); - - // Create a message to sign - let message = b"This is a test message for PQC signature verification"; - - // Sign the message deterministically - let start = Instant::now(); - let signature = match sign(&keypair.secret_key, message) { - Ok(sig) => sig, - Err(e) => { - println!("Error signing message: {e}"); - return; - } - }; - let duration = start.elapsed(); - println!("Signing time: {duration:?}"); - println!("Actual signature size: {} bytes", signature.bytes.len()); - - // Verify the signature - let start = Instant::now(); - match verify(&keypair.public_key, message, &signature) { - Ok(()) => println!("Signature verified successfully!"), - Err(e) => println!("Signature verification failed: {e}"), - } - let duration = start.elapsed(); - println!("Verification time: {duration:?}"); - - // Try to verify with a modified message - let modified_message = b"This is a MODIFIED message for PQC signature verification"; - match verify(&keypair.public_key, modified_message, &signature) { - Ok(()) => println!("ERROR: Signature verified for modified message!"), - Err(_) => println!("Correctly rejected signature for modified message"), - } - - println!(); -} diff --git a/fuzz/.gitignore b/fuzz/.gitignore deleted file mode 100644 index 2eb15f8..0000000 --- a/fuzz/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -target -corpus -coverage diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock deleted file mode 100644 index 1ef40c7..0000000 --- a/fuzz/Cargo.lock +++ /dev/null @@ -1,505 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "arbitrary" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "bindgen" -version = "0.71.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn", -] - -[[package]] -name = "bitcoin-io" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" - -[[package]] -name = "bitcoin_hashes" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" -dependencies = [ - "bitcoin-io", - "hex-conservative", -] - -[[package]] -name = "bitcoinpqc" -version = "0.2.0" -dependencies = [ - "bindgen", - "bitmask-enum", - "cmake", - "hex", - "libc", - "secp256k1", -] - -[[package]] -name = "bitflags" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" - -[[package]] -name = "bitmask-enum" -version = "2.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6cbbb8f56245b5a479b30a62cdc86d26e2f35c2b9f594bc4671654b03851380" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "cc" -version = "1.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "getrandom" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi", -] - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex-conservative" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" -dependencies = [ - "arrayvec", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "libbitcoinpqc-fuzz" -version = "0.0.0" -dependencies = [ - "bitcoinpqc", - "libfuzzer-sys", -] - -[[package]] -name = "libc" -version = "0.2.171" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" - -[[package]] -name = "libfuzzer-sys" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" -dependencies = [ - "arbitrary", - "cc", -] - -[[package]] -name = "libloading" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" -dependencies = [ - "cfg-if", - "windows-targets", -] - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "prettyplease" -version = "0.2.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" - -[[package]] -name = "rand" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "secp256k1" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3dff2d01c9aa65c3186a45ff846bfea52cbe6de3b6320ed2a358d90dad0d76" -dependencies = [ - "bitcoin_hashes", - "rand", - "secp256k1-sys", -] - -[[package]] -name = "secp256k1-sys" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb913707158fadaf0d8702c2db0e857de66eb003ccfdda5924b5f5ac98efb38" -dependencies = [ - "cc", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "syn" -version = "2.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "windows-targets" -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", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[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_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[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_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] - -[[package]] -name = "zerocopy" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml deleted file mode 100644 index 87bea89..0000000 --- a/fuzz/Cargo.toml +++ /dev/null @@ -1,54 +0,0 @@ -[package] -name = "libbitcoinpqc-fuzz" -version = "0.0.0" -publish = false -edition = "2021" - -[package.metadata] -cargo-fuzz = true - -[dependencies] -libfuzzer-sys = "0.4" - -[dependencies.bitcoinpqc] -path = ".." - -# Renamed and repurposed from the original target -[[bin]] -name = "keypair_generation" -path = "fuzz_targets/keypair_generation_fuzz.rs" -test = false -doc = false -bench = false - -# New target for sign and verify operations -[[bin]] -name = "sign_verify" -path = "fuzz_targets/sign_verify_fuzz.rs" -test = false -doc = false -bench = false - -# New target for cross-algorithm verification -[[bin]] -name = "cross_algorithm" -path = "fuzz_targets/cross_algorithm_fuzz.rs" -test = false -doc = false -bench = false - -# New target for key parsing -[[bin]] -name = "key_parsing" -path = "fuzz_targets/key_parsing_fuzz.rs" -test = false -doc = false -bench = false - -# New target for signature parsing -[[bin]] -name = "signature_parsing" -path = "fuzz_targets/signature_parsing_fuzz.rs" -test = false -doc = false -bench = false diff --git a/fuzz/README.md b/fuzz/README.md deleted file mode 100644 index dbc8c7e..0000000 --- a/fuzz/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# Fuzz Testing for libbitcoinpqc - -This directory contains fuzz testing for the libbitcoinpqc library using [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz). - -## Prerequisites - -You need to have cargo-fuzz installed: - -``` -cargo install cargo-fuzz -``` - -## Available Fuzz Targets - -1. **`keypair_generation`** - Tests key pair generation with different algorithms using fuzzed randomness. -2. **`sign_verify`** - Tests signature creation and verification using generated keys and fuzzed messages. -3. **`cross_algorithm`** - Tests verification with mismatched keys and signatures from different algorithms. -4. **`key_parsing`** - Tests parsing of arbitrary byte sequences into `PublicKey` and `SecretKey` structs across algorithms. -5. **`signature_parsing`** - Tests parsing of arbitrary byte sequences into `Signature` structs across algorithms. - -## Running the Fuzz Tests - -To run a specific fuzz target: - -```bash -cargo fuzz run keypair_generation -cargo fuzz run sign_verify -cargo fuzz run cross_algorithm -cargo fuzz run key_parsing -cargo fuzz run signature_parsing -``` - -To run a fuzz target for a specific amount of time: - -```bash -cargo fuzz run keypair_generation -- -max_total_time=60 -``` - -To run a fuzz target with a specific number of iterations: - -```bash -cargo fuzz run keypair_generation -- -runs=1000000 -``` - -To run **all** fuzz targets sequentially, use the provided script (make sure it's executable: `chmod +x fuzz/run_all_fuzzers.sh`): - -```bash -./fuzz/run_all_fuzzers.sh -``` - -This script will iterate through all defined targets **in parallel** using **GNU Parallel**. -If you don't have GNU Parallel installed, the script will output an error. You can install it using your system's package manager: - -- **Debian/Ubuntu:** `sudo apt update && sudo apt install parallel` -- **Fedora:** `sudo dnf install parallel` -- **Arch Linux:** `sudo pacman -S parallel` -- **macOS (Homebrew):** `brew install parallel` - -## Corpus Management - -Cargo-fuzz automatically manages a corpus of interesting inputs. You can find them in the `fuzz/corpus` directory once you've run the fuzz tests. - -## Finding and Reporting Issues - -If a fuzz test finds a crash, it will save the crashing input to `fuzz/artifacts`. You can reproduce the crash with: - -``` -cargo fuzz run target_name fuzz/artifacts/target_name/crash-* -``` - -When reporting an issue found by fuzzing, please include: - -1. The exact command used to run the fuzzer -2. The crash input file -3. The full output of the crash - -## Adding New Fuzz Targets - -To add a new fuzz target: - -1. Create a new Rust file in the `fuzz_targets` directory -2. Add the target to `fuzz/Cargo.toml` -3. Run the new target with `cargo fuzz run target_name` diff --git a/fuzz/artifacts/sign_verify/crash-256ac14220a2ca53e6006f2ed7f036b98864e08a b/fuzz/artifacts/sign_verify/crash-256ac14220a2ca53e6006f2ed7f036b98864e08a deleted file mode 100644 index 2939dba8158241452cdb1e259812683fbb966548..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155 zcmZQzcn^e(?-{`0{rej*@E;9CK*4MVB#9e0c7gy*4;p;|#D9-uCYn4@3L9W#0E==1 E09y-qrvLx| diff --git a/fuzz/fuzz_targets/cross_algorithm_fuzz.rs b/fuzz/fuzz_targets/cross_algorithm_fuzz.rs deleted file mode 100644 index a79806c..0000000 --- a/fuzz/fuzz_targets/cross_algorithm_fuzz.rs +++ /dev/null @@ -1,66 +0,0 @@ -#![no_main] - -use bitcoinpqc::{generate_keypair, sign, verify, Algorithm, Signature}; -use libfuzzer_sys::fuzz_target; - -fuzz_target!(|data: &[u8]| { - if data.len() < 150 { - // Need sufficient bytes for all operations - return; - } - - // Use first 128 bytes for key generation - let key_data = &data[0..128]; - - // Generate two keypairs with different algorithms - let alg1 = Algorithm::SECP256K1_SCHNORR; - let alg2 = Algorithm::ML_DSA_44; - - let keypair1 = match generate_keypair(alg1, key_data) { - Ok(kp) => kp, - Err(_) => return, // Skip if key generation fails - }; - - let keypair2 = match generate_keypair(alg2, key_data) { - Ok(kp) => kp, - Err(_) => return, // Skip if key generation fails - }; - - // Use remaining bytes as message to sign - let message = &data[128..]; - - // Sign with both keys - let signature1 = match sign(&keypair1.secret_key, message) { - Ok(sig) => sig, - Err(_) => return, // Skip if signing fails - }; - - let signature2 = match sign(&keypair2.secret_key, message) { - Ok(sig) => sig, - Err(_) => return, // Skip if signing fails - }; - - // Try to verify with correct key-signature pairs (should succeed) - let _ = verify(&keypair1.public_key, message, &signature1); - let _ = verify(&keypair2.public_key, message, &signature2); - - // Now try incorrect combinations (should fail) - - // Case 1: Use signature1 with public key2 - let sig1_with_wrong_alg = Signature { - algorithm: keypair2.public_key.algorithm, - bytes: signature1.bytes.clone(), - }; - let _ = verify(&keypair2.public_key, message, &sig1_with_wrong_alg); - - // Case 2: Use signature2 with public key1 - let sig2_with_wrong_alg = Signature { - algorithm: keypair1.public_key.algorithm, - bytes: signature2.bytes.clone(), - }; - let _ = verify(&keypair1.public_key, message, &sig2_with_wrong_alg); - - // Case 3: Use original signatures but with the wrong public key - let _ = verify(&keypair1.public_key, message, &signature2); - let _ = verify(&keypair2.public_key, message, &signature1); -}); diff --git a/fuzz/fuzz_targets/key_parsing_fuzz.rs b/fuzz/fuzz_targets/key_parsing_fuzz.rs deleted file mode 100644 index ea4f3a4..0000000 --- a/fuzz/fuzz_targets/key_parsing_fuzz.rs +++ /dev/null @@ -1,40 +0,0 @@ -#![no_main] - -use bitcoinpqc::{algorithm_from_index, PublicKey, SecretKey}; -use libfuzzer_sys::fuzz_target; - -const NUM_ALGORITHMS: u8 = 3; // SECP256K1_SCHNORR, ML_DSA_44, SLH_DSA_128S - -fuzz_target!(|data: &[u8]| { - if data.len() < 2 { - // Need at least 2 bytes: 1 for algorithm, 1+ for key data - return; - } - - // First byte selects algorithm - let alg_byte = data[0]; - let algorithm = algorithm_from_index(alg_byte); - - // Rest of the data is treated as a potential key - let key_data = &data[1..]; - - // Try to interpret this as a secret key - // The key_parsing should correctly validate this without crashing - let sk_result = SecretKey::try_from_slice(algorithm, key_data); - if key_data.len() == bitcoinpqc::secret_key_size(algorithm) { - // If length matches, it should parse correctly - // (assuming bytewise validation passes) - let _ = sk_result.unwrap_or_else(|_| { - panic!( - "Secret key parsing failed! Algorithm: {}", - algorithm.debug_name() - ) - }); - } else { - // Otherwise it should return an error - assert!( - sk_result.is_err(), - "Parsing should fail for invalid key length!" - ); - } -}); diff --git a/fuzz/fuzz_targets/keypair_generation_fuzz.rs b/fuzz/fuzz_targets/keypair_generation_fuzz.rs deleted file mode 100644 index 2344ad2..0000000 --- a/fuzz/fuzz_targets/keypair_generation_fuzz.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![no_main] - -use bitcoinpqc::{algorithm_from_index, generate_keypair}; -use libfuzzer_sys::fuzz_target; - -fuzz_target!(|data: &[u8]| { - if data.len() < 130 { - // Need at least 1 byte for algorithm + 129 bytes for key seed - return; - } - - // First byte selects algorithm - let alg_byte = data[0]; - let algorithm = algorithm_from_index(alg_byte); - - // Rest is key generation data - let key_data = &data[1..]; // Should be 129+ bytes - - // Try to generate a keypair - let keypair_result = generate_keypair(algorithm, key_data); - assert!( - keypair_result.is_ok(), - "Keypair generation failed! Algorithm: {}", - algorithm.debug_name() - ); - let _keypair = keypair_result.unwrap(); - // Success! -}); diff --git a/fuzz/fuzz_targets/sign_verify_fuzz.rs b/fuzz/fuzz_targets/sign_verify_fuzz.rs deleted file mode 100644 index a8b1156..0000000 --- a/fuzz/fuzz_targets/sign_verify_fuzz.rs +++ /dev/null @@ -1,77 +0,0 @@ -#![no_main] - -use bitcoinpqc::{algorithm_from_index, generate_keypair, sign, verify}; -use libfuzzer_sys::fuzz_target; - -fuzz_target!(|data: &[u8]| { - // Need sufficient bytes for all operations: - // 1 byte for algorithm + 128 bytes for key generation + 32 bytes for message (Secp256k1 requires 32) - if data.len() < 1 + 128 + 32 { - return; - } - - // Use first byte to select an algorithm - let alg_byte = data[0]; - let algorithm = algorithm_from_index(alg_byte); - - // Use 128 bytes for key generation - let key_data = &data[1..129]; - - // Try to generate a keypair - let keypair_result = generate_keypair(algorithm, key_data); - if let Err(err) = &keypair_result { - panic!( - "Key generation failed for algorithm: {}, error: {:?}", - algorithm.debug_name(), - err - ); - } - let keypair = keypair_result.unwrap(); - - // Use remaining bytes as message to sign - // We've already checked above that we have at least 32 bytes left - let message = &data[129..]; - - // Try to sign the message - let signature_result = sign(&keypair.secret_key, message); - if let Err(err) = &signature_result { - panic!( - "Signing failed for algorithm: {}, error: {:?}", - algorithm.debug_name(), - err - ); - } - let signature = signature_result.unwrap(); - - // Try to verify the signature with the correct public key - let verify_result = verify(&keypair.public_key, message, &signature); - if let Err(err) = &verify_result { - panic!("Verification failed for a signature generated with the corresponding private key! Algorithm: {}, error: {:?}", - algorithm.debug_name(), err); - } - - // Also try some invalid cases (if we have a valid signature) - if message.len() > 1 { - // Try with modified message - let mut modified_msg = message.to_vec(); - modified_msg[0] ^= 0xFF; // Flip bits in first byte - let verify_result_bad_msg = verify(&keypair.public_key, &modified_msg, &signature); - assert!( - verify_result_bad_msg.is_err(), - "Verification should fail with modified message! Algorithm: {}", - algorithm.debug_name() - ); - } - - if signature.bytes.len() > 1 { - // Try with modified signature - let mut modified_sig = signature.clone(); - modified_sig.bytes[0] ^= 0xFF; // Flip bits in first byte - let verify_result_bad_sig = verify(&keypair.public_key, message, &modified_sig); - assert!( - verify_result_bad_sig.is_err(), - "Verification should fail with modified signature! Algorithm: {}", - algorithm.debug_name() - ); - } -}); diff --git a/fuzz/fuzz_targets/signature_parsing_fuzz.rs b/fuzz/fuzz_targets/signature_parsing_fuzz.rs deleted file mode 100644 index 8ab27e9..0000000 --- a/fuzz/fuzz_targets/signature_parsing_fuzz.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![no_main] - -use bitcoinpqc::{algorithm_from_index, Signature}; -use libfuzzer_sys::fuzz_target; - -const NUM_ALGORITHMS: u8 = 3; // SECP256K1_SCHNORR, ML_DSA_44, SLH_DSA_128S - -fuzz_target!(|data: &[u8]| { - if data.is_empty() { - return; // Need at least one byte for algorithm selection - } - - // Use first byte to select an algorithm - let alg_byte = data[0]; - let algorithm = algorithm_from_index(alg_byte); - - // Use remaining bytes as potential signature data - let sig_data = &data[1..]; - - // Attempt to parse as Signature - let _ = Signature::try_from_slice(algorithm, sig_data); -}); diff --git a/fuzz/output.txt b/fuzz/output.txt deleted file mode 100644 index cb627d5..0000000 --- a/fuzz/output.txt +++ /dev/null @@ -1,176 +0,0 @@ -/fuzz/run_all_fuzzers.sh 9.1s  Fri Apr 25 10:46:23 2025 -Running all fuzz targets in parallel: keypair_generation sign_verify cross_algorithm key_parsing signature_parsing ---- Starting fuzzer: cross_algorithm --- ---- Starting fuzzer: keypair_generation --- ---- Starting fuzzer: sign_verify --- ---- Starting fuzzer: key_parsing --- ---- Starting fuzzer: signature_parsing --- - Running `fuzz/target/x86_64-unknown-linux-gnu/release/cross_algorithm -artifact_prefix=/home/hunter/Projects/pqc/libbitcoinpqc/fuzz/artifacts/cross_algorithm/ /home/hunter/Projects/pqc/libbitcoinpqc/fuzz/corpus/cross_algorithm` -INFO: Running with entropic power schedule (0xFF, 100). -INFO: Seed: 2416094420 -INFO: Loaded 1 modules (21002 inline 8-bit counters): 21002 [0x5c4378f253f0, 0x5c4378f2a5fa), -INFO: Loaded 1 PC tables (21002 PCs): 21002 [0x5c4378f2a600,0x5c4378f7c6a0), -INFO: 0 files found in /home/hunter/Projects/pqc/libbitcoinpqc/fuzz/corpus/cross_algorithm -INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes -INFO: A corpus is not provided, starting from an empty corpus -#2 INITED cov: 19 ft: 20 corp: 1/1b exec/s: 0 rss: 48Mb - Finished `release` profile [optimized + debuginfo] target(s) in 2.69s - Finished `release` profile [optimized + debuginfo] target(s) in 1.18s - Running `fuzz/target/x86_64-unknown-linux-gnu/release/keypair_generation -artifact_prefix=/home/hunter/Projects/pqc/libbitcoinpqc/fuzz/artifacts/keypair_generation/ /home/hunter/Projects/pqc/libbitcoinpqc/fuzz/corpus/keypair_generation` -INFO: Running with entropic power schedule (0xFF, 100). -INFO: Seed: 2420079927 -INFO: Loaded 1 modules (20737 inline 8-bit counters): 20737 [0x604bb8a91270, 0x604bb8a96371), -INFO: Loaded 1 PC tables (20737 PCs): 20737 [0x604bb8a96378,0x604bb8ae7388), -INFO: 4 files found in /home/hunter/Projects/pqc/libbitcoinpqc/fuzz/corpus/keypair_generation -INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes -INFO: seed corpus: files: 4 min: 129b max: 129b total: 516b rss: 47Mb - Finished `release` profile [optimized + debuginfo] target(s) in 1.19s - Running `fuzz/target/x86_64-unknown-linux-gnu/release/sign_verify -artifact_prefix=/home/hunter/Projects/pqc/libbitcoinpqc/fuzz/artifacts/sign_verify/ /home/hunter/Projects/pqc/libbitcoinpqc/fuzz/corpus/sign_verify` -INFO: Running with entropic power schedule (0xFF, 100). -INFO: Seed: 2427464392 -INFO: Loaded 1 modules (20974 inline 8-bit counters): 20974 [0x63f5c0000430, 0x63f5c000561e), -INFO: Loaded 1 PC tables (20974 PCs): 20974 [0x63f5c0005620,0x63f5c0057500), -INFO: 0 files found in /home/hunter/Projects/pqc/libbitcoinpqc/fuzz/corpus/sign_verify -INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes -INFO: A corpus is not provided, starting from an empty corpus -#2 INITED cov: 19 ft: 20 corp: 1/1b exec/s: 0 rss: 45Mb - Finished `release` profile [optimized + debuginfo] target(s) in 0.56s - Running `fuzz/target/x86_64-unknown-linux-gnu/release/key_parsing -artifact_prefix=/home/hunter/Projects/pqc/libbitcoinpqc/fuzz/artifacts/key_parsing/ /home/hunter/Projects/pqc/libbitcoinpqc/fuzz/corpus/key_parsing` -INFO: Running with entropic power schedule (0xFF, 100). -INFO: Seed: 2432138094 -INFO: Loaded 1 modules (20738 inline 8-bit counters): 20738 [0x645adaae9270, 0x645adaaee372), -INFO: Loaded 1 PC tables (20738 PCs): 20738 [0x645adaaee378,0x645adab3f398), -INFO: 0 files found in /home/hunter/Projects/pqc/libbitcoinpqc/fuzz/corpus/key_parsing -INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes -INFO: A corpus is not provided, starting from an empty corpus -#2 INITED cov: 37 ft: 38 corp: 1/1b exec/s: 0 rss: 45Mb -#4 NEW cov: 39 ft: 40 corp: 2/2b lim: 4 exec/s: 0 rss: 45Mb L: 1/1 MS: 2 ShuffleBytes-ChangeByte- -#15 NEW cov: 41 ft: 42 corp: 3/4b lim: 4 exec/s: 0 rss: 45Mb L: 2/2 MS: 1 InsertByte- -#21 NEW cov: 43 ft: 44 corp: 4/6b lim: 4 exec/s: 0 rss: 45Mb L: 2/2 MS: 1 ChangeBinInt- -#138 REDUCE cov: 43 ft: 44 corp: 4/5b lim: 4 exec/s: 0 rss: 47Mb L: 1/2 MS: 2 ShuffleBytes-EraseBytes- -#375 REDUCE cov: 43 ft: 44 corp: 4/4b lim: 6 exec/s: 0 rss: 47Mb L: 1/1 MS: 2 ShuffleBytes-EraseBytes- -#680 REDUCE cov: 44 ft: 45 corp: 5/12b lim: 8 exec/s: 0 rss: 47Mb L: 8/8 MS: 5 InsertRepeatedBytes-EraseBytes-InsertByte-ChangeByte-CrossOver- -#3550 REDUCE cov: 50 ft: 51 corp: 6/45b lim: 33 exec/s: 0 rss: 48Mb L: 33/33 MS: 5 CopyPart-ChangeByte-CopyPart-InsertRepeatedBytes-CrossOver- - Finished `release` profile [optimized + debuginfo] target(s) in 0.02s - Running `fuzz/target/x86_64-unknown-linux-gnu/release/signature_parsing -artifact_prefix=/home/hunter/Projects/pqc/libbitcoinpqc/fuzz/artifacts/signature_parsing/ /home/hunter/Projects/pqc/libbitcoinpqc/fuzz/corpus/signature_parsing` -INFO: Running with entropic power schedule (0xFF, 100). -INFO: Seed: 2512484958 -INFO: Loaded 1 modules (20712 inline 8-bit counters): 20712 [0x563d379d6270, 0x563d379db358), -INFO: Loaded 1 PC tables (20712 PCs): 20712 [0x563d379db358,0x563d37a2c1d8), -INFO: 0 files found in /home/hunter/Projects/pqc/libbitcoinpqc/fuzz/corpus/signature_parsing -INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes -INFO: A corpus is not provided, starting from an empty corpus -#2 INITED cov: 28 ft: 29 corp: 1/1b exec/s: 0 rss: 45Mb -#6 NEW cov: 29 ft: 30 corp: 2/3b lim: 4 exec/s: 0 rss: 45Mb L: 2/2 MS: 4 ShuffleBytes-CopyPart-ShuffleBytes-ChangeByte- -#20 NEW cov: 30 ft: 31 corp: 3/7b lim: 4 exec/s: 0 rss: 47Mb L: 4/4 MS: 4 CrossOver-CopyPart-CMP-ChangeBinInt- DE: "\377\377"- -#31 NEW cov: 31 ft: 32 corp: 4/9b lim: 4 exec/s: 0 rss: 47Mb L: 2/4 MS: 1 InsertByte- -#123 REDUCE cov: 31 ft: 32 corp: 4/8b lim: 4 exec/s: 0 rss: 47Mb L: 1/4 MS: 2 ChangeBinInt-EraseBytes- -#180 REDUCE cov: 31 ft: 32 corp: 4/7b lim: 4 exec/s: 0 rss: 47Mb L: 3/3 MS: 2 ShuffleBytes-EraseBytes- -#191 REDUCE cov: 31 ft: 32 corp: 4/6b lim: 4 exec/s: 0 rss: 47Mb L: 1/3 MS: 1 EraseBytes- -#200 REDUCE cov: 31 ft: 32 corp: 4/5b lim: 4 exec/s: 0 rss: 47Mb L: 2/2 MS: 4 CrossOver-CopyPart-ChangeBit-EraseBytes- -#379 REDUCE cov: 31 ft: 32 corp: 4/4b lim: 4 exec/s: 0 rss: 47Mb L: 1/1 MS: 4 CMP-ShuffleBytes-ChangeBit-EraseBytes- DE: "\001\000"- -#830 REDUCE cov: 32 ft: 33 corp: 5/12b lim: 8 exec/s: 0 rss: 48Mb L: 8/8 MS: 1 InsertRepeatedBytes- -#6967 REDUCE cov: 37 ft: 38 corp: 6/77b lim: 68 exec/s: 0 rss: 48Mb L: 65/65 MS: 2 CopyPart-InsertRepeatedBytes- -#5 INITED cov: 41 ft: 42 corp: 4/516b exec/s: 0 rss: 52Mb -#21 NEW cov: 42 ft: 44 corp: 5/615b lim: 129 exec/s: 0 rss: 52Mb L: 99/129 MS: 1 EraseBytes- - NEW_FUNC[1/4]: 0x5c4378b045e0 in core::ptr::drop_in_place$LT$bitcoinpqc..SecretKey$GT$::h6059cf8040e36a38 /home/hunter/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524 -#47 REDUCE cov: 42 ft: 44 corp: 5/605b lim: 129 exec/s: 0 rss: 52Mb L: 89/129 MS: 1 EraseBytes- -#52 REDUCE cov: 42 ft: 44 corp: 5/585b lim: 129 exec/s: 0 rss: 52Mb L: 69/129 MS: 5 InsertByte-ShuffleBytes-CrossOver-ChangeBinInt-EraseBytes- - NEW_FUNC[1/1]: 0x645ada745ee0 in _$LT$bitcoinpqc..SecretKey$u20$as$u20$core..ops..drop..Drop$GT$::drop::hfd0245cc145361e9 /home/hunter/Projects/pqc/libbitcoinpqc/src/lib.rs:274 -#3691 NEW cov: 58 ft: 59 corp: 7/78b lim: 33 exec/s: 0 rss: 48Mb L: 33/33 MS: 1 CrossOver- -#3744 NEW cov: 60 ft: 61 corp: 8/111b lim: 33 exec/s: 0 rss: 48Mb L: 33/33 MS: 3 ShuffleBytes-ChangeBinInt-ChangeByte- -#7342 NEW cov: 63 ft: 64 corp: 9/176b lim: 68 exec/s: 0 rss: 48Mb L: 65/65 MS: 3 CMP-CrossOver-InsertByte- DE: "\001\000"- - NEW_FUNC[2/4]: 0x5c4378b80ee0 in _$LT$bitcoinpqc..SecretKey$u20$as$u20$core..ops..drop..Drop$GT$::drop::hfd0245cc145361e9 /home/hunter/Projects/pqc/libbitcoinpqc/src/lib.rs:274 -#16437 NEW cov: 55 ft: 57 corp: 2/158b lim: 163 exec/s: 0 rss: 50Mb L: 157/157 MS: 5 CopyPart-CopyPart-InsertRepeatedBytes-InsertRepeatedBytes-CMP- DE: "\377\377\377\377\377\377\377z"- - NEW_FUNC[1/2]: 0x5c4378b07bb0 in _$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..clone..Clone$GT$::clone::hc345d965bd3841bb /home/hunter/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3318 - NEW_FUNC[2/2]: 0x5c4378b848d0 in bitcoinpqc::verify::h33067318d4f4719c /home/hunter/Projects/pqc/libbitcoinpqc/src/lib.rs:561 -#16438 NEW cov: 92 ft: 99 corp: 3/315b lim: 163 exec/s: 0 rss: 52Mb L: 157/157 MS: 1 ChangeASCIIInt- -#29236 NEW cov: 64 ft: 65 corp: 10/209b lim: 285 exec/s: 0 rss: 50Mb L: 33/65 MS: 4 ShuffleBytes-ChangeBit-InsertRepeatedBytes-CrossOver- -#16486 REDUCE cov: 92 ft: 99 corp: 3/311b lim: 163 exec/s: 0 rss: 56Mb L: 153/157 MS: 3 CopyPart-EraseBytes-PersAutoDict- DE: "\377\377\377\377\377\377\377z"- -#16574 REDUCE cov: 92 ft: 99 corp: 3/308b lim: 163 exec/s: 16574 rss: 60Mb L: 150/157 MS: 3 InsertByte-EraseBytes-InsertRepeatedBytes- -#90 REDUCE cov: 42 ft: 44 corp: 5/583b lim: 129 exec/s: 90 rss: 52Mb L: 67/129 MS: 3 CMP-ChangeBinInt-EraseBytes- DE: "\377\377\377\377"- -#92 REDUCE cov: 42 ft: 44 corp: 5/540b lim: 129 exec/s: 92 rss: 52Mb L: 24/129 MS: 2 CMP-CrossOver- DE: "\377\377\377\377\377\377\377\377"- -#123 REDUCE cov: 42 ft: 44 corp: 5/537b lim: 129 exec/s: 123 rss: 52Mb L: 21/129 MS: 1 EraseBytes- -#125 REDUCE cov: 42 ft: 44 corp: 5/528b lim: 129 exec/s: 125 rss: 52Mb L: 12/129 MS: 2 CMP-EraseBytes- DE: "\000\000\000\000\000\000\000f"- -#146 REDUCE cov: 42 ft: 44 corp: 5/522b lim: 129 exec/s: 146 rss: 52Mb L: 6/129 MS: 1 EraseBytes- - NEW_FUNC[1/6]: 0x63f5bfbe05e0 in core::ptr::drop_in_place$LT$bitcoinpqc..SecretKey$GT$::hbe70475d19333e6a /home/hunter/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524 - NEW_FUNC[2/6]: 0x63f5bfbe3bb0 in _$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..clone..Clone$GT$::clone::hfa906a19917719ff /home/hunter/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3318 -#15631 NEW cov: 71 ft: 73 corp: 2/157b lim: 156 exec/s: 15631 rss: 49Mb L: 156/156 MS: 4 ChangeByte-InsertRepeatedBytes-InsertRepeatedBytes-CopyPart- -#163 REDUCE cov: 42 ft: 44 corp: 5/520b lim: 129 exec/s: 81 rss: 52Mb L: 4/129 MS: 2 ShuffleBytes-EraseBytes- -#1048576 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 524288 rss: 163Mb -#256 pulse cov: 42 ft: 44 corp: 5/520b lim: 129 exec/s: 85 rss: 53Mb -#264 REDUCE cov: 42 ft: 44 corp: 5/518b lim: 129 exec/s: 88 rss: 53Mb L: 2/129 MS: 1 EraseBytes- -#265 REDUCE cov: 42 ft: 44 corp: 5/517b lim: 129 exec/s: 88 rss: 53Mb L: 1/129 MS: 1 EraseBytes- -#2097152 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 699050 rss: 245Mb -#2097152 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 419430 rss: 277Mb -#4194304 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 599186 rss: 444Mb -#512 pulse cov: 42 ft: 44 corp: 5/517b lim: 129 exec/s: 73 rss: 53Mb -#4194304 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 466033 rss: 510Mb -#1024 pulse cov: 42 ft: 44 corp: 5/517b lim: 136 exec/s: 93 rss: 56Mb -#8388608 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 559240 rss: 560Mb -#15674 REDUCE cov: 71 ft: 73 corp: 2/153b lim: 156 exec/s: 979 rss: 52Mb L: 152/152 MS: 3 ChangeBit-ChangeBinInt-EraseBytes- -#8388608 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 441505 rss: 524Mb -#2048 pulse cov: 42 ft: 44 corp: 5/517b lim: 143 exec/s: 81 rss: 60Mb -#16777216 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 559240 rss: 561Mb -#16777216 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 453438 rss: 524Mb -#15781 REDUCE cov: 75 ft: 77 corp: 3/305b lim: 156 exec/s: 292 rss: 53Mb L: 152/152 MS: 2 CopyPart-CMP- DE: "\261\036\000\000\000\000\000\000"- -#32768 pulse cov: 92 ft: 99 corp: 3/308b lim: 317 exec/s: 595 rss: 367Mb -#4096 pulse cov: 42 ft: 44 corp: 5/517b lim: 164 exec/s: 71 rss: 72Mb -#33554432 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 559240 rss: 561Mb -^[[2~#33554432 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 453438 rss: 524Mb -#15893 REDUCE cov: 75 ft: 77 corp: 3/303b lim: 156 exec/s: 209 rss: 55Mb L: 150/152 MS: 2 CrossOver-InsertRepeatedBytes- -#16096 REDUCE cov: 75 ft: 77 corp: 3/302b lim: 156 exec/s: 149 rss: 59Mb L: 151/151 MS: 3 CopyPart-ChangeByte-CrossOver- -#67108864 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 559240 rss: 561Mb -#8192 pulse cov: 42 ft: 44 corp: 5/517b lim: 206 exec/s: 60 rss: 95Mb -#67108864 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 453438 rss: 525Mb -#65536 pulse cov: 92 ft: 99 corp: 3/308b lim: 643 exec/s: 383 rss: 368Mb -#16316 REDUCE cov: 75 ft: 77 corp: 3/301b lim: 156 exec/s: 91 rss: 67Mb L: 150/150 MS: 5 CrossOver-ChangeByte-ChangeBinInt-EraseBytes-CopyPart- -#16384 pulse cov: 75 ft: 77 corp: 3/301b lim: 156 exec/s: 84 rss: 69Mb -#134217728 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 559240 rss: 561Mb -#16384 pulse cov: 42 ft: 44 corp: 5/517b lim: 286 exec/s: 57 rss: 141Mb -#16817 REDUCE cov: 79 ft: 81 corp: 4/451b lim: 156 exec/s: 57 rss: 86Mb L: 150/150 MS: 1 ChangeByte- -#134217728 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 451911 rss: 525Mb -#131072 pulse cov: 92 ft: 99 corp: 3/308b lim: 1300 exec/s: 325 rss: 368Mb -#17749 NEW cov: 82 ft: 85 corp: 5/602b lim: 163 exec/s: 39 rss: 112Mb L: 151/151 MS: 2 ChangeBit-InsertByte- -#268435456 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 556920 rss: 561Mb -#18271 REDUCE cov: 82 ft: 85 corp: 5/601b lim: 163 exec/s: 36 rss: 124Mb L: 150/150 MS: 2 CrossOver-EraseBytes- -#32768 pulse cov: 42 ft: 44 corp: 5/517b lim: 446 exec/s: 56 rss: 241Mb -#268435456 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 451152 rss: 526Mb -#262144 pulse cov: 92 ft: 99 corp: 3/308b lim: 2600 exec/s: 302 rss: 368Mb -#536870912 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 556342 rss: 561Mb -#536870912 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 451911 rss: 527Mb -#65536 pulse cov: 42 ft: 44 corp: 5/517b lim: 770 exec/s: 54 rss: 377Mb -#524288 pulse cov: 92 ft: 99 corp: 3/308b lim: 4096 exec/s: 291 rss: 369Mb -#1073741824 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 556631 rss: 561Mb -#1073741824 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 451531 rss: 527Mb -#131072 pulse cov: 42 ft: 44 corp: 5/517b lim: 1421 exec/s: 52 rss: 379Mb -#32768 pulse cov: 82 ft: 85 corp: 5/601b lim: 301 exec/s: 13 rss: 370Mb -#1048576 pulse cov: 92 ft: 99 corp: 3/308b lim: 4096 exec/s: 283 rss: 369Mb -#2147483648 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 554189 rss: 563Mb -#2147483648 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 447485 rss: 528Mb -#262144 pulse cov: 42 ft: 44 corp: 5/517b lim: 2733 exec/s: 50 rss: 379Mb -#65536 pulse cov: 82 ft: 85 corp: 5/601b lim: 625 exec/s: 8 rss: 373Mb -#2097152 pulse cov: 92 ft: 99 corp: 3/308b lim: 4096 exec/s: 275 rss: 370Mb -#4294967296 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 542156 rss: 563Mb -#4294967296 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 436746 rss: 528Mb -#524288 pulse cov: 42 ft: 44 corp: 5/517b lim: 4096 exec/s: 49 rss: 380Mb -#4194304 pulse cov: 92 ft: 99 corp: 3/308b lim: 4096 exec/s: 263 rss: 397Mb -#8589934592 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 513260 rss: 563Mb -#131072 pulse cov: 82 ft: 85 corp: 5/601b lim: 1280 exec/s: 7 rss: 397Mb -#8589934592 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 419922 rss: 531Mb -#1048576 pulse cov: 42 ft: 44 corp: 5/517b lim: 4096 exec/s: 48 rss: 382Mb -#8388608 pulse cov: 92 ft: 99 corp: 3/308b lim: 4096 exec/s: 263 rss: 397Mb -#17179869184 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 530439 rss: 563Mb -#262144 pulse cov: 82 ft: 85 corp: 5/601b lim: 2589 exec/s: 7 rss: 397Mb -#17179869184 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 422182 rss: 531Mb -#2097152 pulse cov: 42 ft: 44 corp: 5/517b lim: 4096 exec/s: 47 rss: 382Mb -#16777216 pulse cov: 92 ft: 99 corp: 3/308b lim: 4096 exec/s: 250 rss: 397Mb -#34359738368 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 492323 rss: 563Mb -#524288 pulse cov: 82 ft: 85 corp: 5/601b lim: 4096 exec/s: 6 rss: 397Mb -#34359738368 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 405913 rss: 531Mb -#4194304 pulse cov: 42 ft: 44 corp: 5/517b lim: 4096 exec/s: 47 rss: 382Mb -#33554432 pulse cov: 92 ft: 99 corp: 3/308b lim: 4096 exec/s: 255 rss: 397Mb -#68719476736 pulse cov: 37 ft: 38 corp: 6/77b lim: 4096 exec/s: 514814 rss: 563Mb -#1048576 pulse cov: 82 ft: 85 corp: 5/601b lim: 4096 exec/s: 6 rss: 397Mb -#68719476736 pulse cov: 64 ft: 65 corp: 10/209b lim: 4096 exec/s: 421643 rss: 531Mb -#8388608 pulse cov: 42 ft: 44 corp: 5/517b lim: 4096 exec/s: 48 rss: 382Mb diff --git a/fuzz/run_all_fuzzers.sh b/fuzz/run_all_fuzzers.sh deleted file mode 100755 index 02bfc21..0000000 --- a/fuzz/run_all_fuzzers.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -# Exit immediately if a command exits with a non-zero status. -set -e - -# Define the fuzz targets to run (names must match Cargo.toml) -TARGETS="keypair_generation sign_verify cross_algorithm key_parsing signature_parsing" - -echo "Running all fuzz targets in parallel: $TARGETS" - -# Check if GNU Parallel is installed -if ! command -v parallel &> /dev/null -then - echo "Error: GNU Parallel is not installed. Please install it to run fuzzers in parallel." - echo "(e.g., 'sudo apt install parallel' or 'brew install parallel')" - exit 1 -fi - -# Run targets in parallel using GNU Parallel -# -j 0: Run one job per CPU core. Adjust if needed (e.g., -j 4 for 4 cores). -# --line-buffer: Buffer output line by line, helps prevent excessively interleaved output. -# {}: Placeholder for each target name. - -printf "%s\n" $TARGETS | parallel -j 0 --line-buffer \ - 'echo "--- Starting fuzzer: {} ---"; cargo fuzz run "{}"; echo "--- Finished fuzzer: {} ---"' - - -echo "-------------------------------------" -echo "All parallel fuzz jobs launched (may still be running)." diff --git a/nodejs/.gitignore b/nodejs/.gitignore deleted file mode 100644 index 73db82f..0000000 --- a/nodejs/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -# Node.js -node_modules/ -npm-debug.log -yarn-debug.log -yarn-error.log - -# Build artifacts -dist/ -build/ -*.node - -# Coverage -coverage/ - -# OS specific -.DS_Store -.env - -# IDE specific -.idea/ -.vscode/ -*.swp -*.swo - -c_sources diff --git a/nodejs/README.md b/nodejs/README.md deleted file mode 100644 index 9cec3fc..0000000 --- a/nodejs/README.md +++ /dev/null @@ -1,167 +0,0 @@ -# BitcoinPQC - NodeJS TypeScript Bindings - -TypeScript bindings for the [libbitcoinpqc](https://github.com/bitcoin/libbitcoinpqc) library, which provides post-quantum cryptographic signature algorithms for use with BIP-360 and the Bitcoin QuBit soft fork. - -## Features - -- Full TypeScript support with typings -- Clean, ergonomic API -- Compatible with NodeJS 16+ -- Works with both PQC algorithms: - - ML-DSA-44 (formerly CRYSTALS-Dilithium) - - SLH-DSA-Shake-128s (formerly SPHINCS+) - -## Installation - -```bash -npm install bitcoinpqc -``` - -### Prerequisites - -This package requires the native `libbitcoinpqc` library to be installed on your system. See the main [libbitcoinpqc README](https://github.com/bitcoin/libbitcoinpqc) for instructions on installing the C library. - -## API Usage - -```typescript -import { Algorithm, generateKeyPair, sign, verify } from 'bitcoinpqc'; -import crypto from 'crypto'; - -// Generate random data for key generation -const randomData = crypto.randomBytes(128); - -// Generate a key pair using ML-DSA-44 (CRYSTALS-Dilithium) -const keypair = generateKeyPair(Algorithm.ML_DSA_44, randomData); - -// Create a message to sign -const message = Buffer.from('Message to sign'); - -// Sign the message deterministically -const signature = sign(keypair.secretKey, message); - -// Verify the signature -verify(keypair.publicKey, message, signature); -// If verification fails, it will throw a PqcError - -// You can also verify using the raw signature bytes -verify(keypair.publicKey, message, signature.bytes); -``` - -## API Reference - -### Enums - -#### `Algorithm` - -```typescript -enum Algorithm { - /** BIP-340 Schnorr + X-Only - Elliptic Curve Digital Signature Algorithm */ - SECP256K1_SCHNORR = 0, - /** ML-DSA-44 (CRYSTALS-Dilithium) - Lattice-based signature scheme */ - ML_DSA_44 = 1, - /** SLH-DSA-Shake-128s (SPHINCS+) - Hash-based signature scheme */ - SLH_DSA_SHAKE_128S = 2 -} -``` - -### Classes - -#### `PublicKey` - -```typescript -class PublicKey { - readonly algorithm: Algorithm; - readonly bytes: Uint8Array; -} -``` - -#### `SecretKey` - -```typescript -class SecretKey { - readonly algorithm: Algorithm; - readonly bytes: Uint8Array; -} -``` - -#### `KeyPair` - -```typescript -class KeyPair { - readonly publicKey: PublicKey; - readonly secretKey: SecretKey; -} -``` - -#### `Signature` - -```typescript -class Signature { - readonly algorithm: Algorithm; - readonly bytes: Uint8Array; -} -``` - -#### `PqcError` - -```typescript -class PqcError extends Error { - readonly code: ErrorCode; - constructor(code: ErrorCode, message?: string); -} - -enum ErrorCode { - OK = 0, - BAD_ARGUMENT = -1, - BAD_KEY = -2, - BAD_SIGNATURE = -3, - NOT_IMPLEMENTED = -4 -} -``` - -### Functions - -#### `publicKeySize(algorithm: Algorithm): number` - -Get the public key size for an algorithm. - -#### `secretKeySize(algorithm: Algorithm): number` - -Get the secret key size for an algorithm. - -#### `signatureSize(algorithm: Algorithm): number` - -Get the signature size for an algorithm. - -#### `generateKeyPair(algorithm: Algorithm, randomData: Uint8Array): KeyPair` - -Generate a key pair for the specified algorithm. The `randomData` must be at least 128 bytes. - -#### `sign(secretKey: SecretKey, message: Uint8Array): Signature` - -Sign a message using the specified secret key. The signature is deterministic based on the message and key. - -#### `verify(publicKey: PublicKey, message: Uint8Array, signature: Signature | Uint8Array): void` - -Verify a signature using the specified public key. Throws a `PqcError` if verification fails. - -## Algorithm Characteristics - -| Algorithm | Public Key Size | Secret Key Size | Signature Size | Security Level | -| ------------------ | --------------- | --------------- | -------------- | -------------- | -| 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 | - -## Security Notes - -- 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. - -## BIP-360 Compliance - -This library implements the TypeScript bindings for cryptographic primitives required by [BIP-360](https://github.com/bitcoin/bips/blob/master/bip-0360.mediawiki), which defines the standard for post-quantum resistant signatures in Bitcoin. - -## License - -This project is licensed under the MIT License - see the LICENSE file for details. diff --git a/nodejs/binding.gyp b/nodejs/binding.gyp deleted file mode 100644 index e9d385e..0000000 --- a/nodejs/binding.gyp +++ /dev/null @@ -1,79 +0,0 @@ -{ - "targets": [ - { - "target_name": "bitcoinpqc", - "sources": [ - "src/native/bitcoinpqc_addon.cc", - "src/c_sources/bitcoinpqc.c", - "src/c_sources/ml_dsa/keygen.c", - "src/c_sources/ml_dsa/sign.c", - "src/c_sources/ml_dsa/verify.c", - "src/c_sources/ml_dsa/utils.c", - "src/c_sources/slh_dsa/keygen.c", - "src/c_sources/slh_dsa/sign.c", - "src/c_sources/slh_dsa/verify.c", - "src/c_sources/slh_dsa/utils.c", - "src/c_sources/dilithium_ref/sign.c", - "src/c_sources/dilithium_ref/packing.c", - "src/c_sources/dilithium_ref/polyvec.c", - "src/c_sources/dilithium_ref/poly.c", - "src/c_sources/dilithium_ref/ntt.c", - "src/c_sources/dilithium_ref/reduce.c", - "src/c_sources/dilithium_ref/rounding.c", - "src/c_sources/dilithium_ref/fips202.c", - "src/c_sources/dilithium_ref/symmetric-shake.c", - "src/c_sources/randombytes_custom.c", - "src/c_sources/sphincsplus_ref/address.c", - "src/c_sources/sphincsplus_ref/fors.c", - "src/c_sources/sphincsplus_ref/hash_shake.c", - "src/c_sources/sphincsplus_ref/merkle.c", - "src/c_sources/sphincsplus_ref/sign.c", - "src/c_sources/sphincsplus_ref/thash_shake_simple.c", - "src/c_sources/sphincsplus_ref/utils.c", - "src/c_sources/sphincsplus_ref/utilsx1.c", - "src/c_sources/sphincsplus_ref/wots.c", - "src/c_sources/sphincsplus_ref/wotsx1.c", - "src/c_sources/sphincsplus_ref/fips202.c" - ], - "include_dirs": [ - "=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", - "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.26.10", - "@babel/types": "^7.26.10", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", - "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.26.5", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", - "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.10" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", - "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.26.10" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz", - "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.10", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", - "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "license": "MIT", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "29.5.14", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", - "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "node_modules/@types/node": { - "version": "20.17.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.25.tgz", - "integrity": "sha512-bT+r2haIlplJUYtlZrEanFHdPIZTeiMeh/fSOEbOOfWf9uTn+lg8g0KU6Q3iMgjd9FLuuMAgfCNSkjUbxL6E3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "license": "ISC" - }, - "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001706", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz", - "integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.123", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.123.tgz", - "integrity": "sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==", - "dev": true, - "license": "ISC" - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/exponential-backoff": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", - "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true, - "license": "ISC" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jake": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", - "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "license": "ISC" - }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/node-gyp": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", - "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.13 || ^14.13 || >=16" - } - }, - "node_modules/node-gyp/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, - "license": "MIT" - }, - "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", - "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true, - "license": "ISC" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", - "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-jest": { - "version": "29.2.6", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.6.tgz", - "integrity": "sha512-yTNZVZqc8lSixm+QGVFcPe6+yj7+TWZwIesuOWvfcn4B9bz5x4NDzVCQQjOs7Hfouu36aEqfEbo9Qpo+gq8dDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "bs-logger": "^0.2.6", - "ejs": "^3.1.10", - "fast-json-stable-stringify": "^2.1.0", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "^4.1.2", - "make-error": "^1.3.6", - "semver": "^7.7.1", - "yargs-parser": "^21.1.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "node_modules/ts-jest/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", - "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true, - "license": "MIT" - }, - "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "license": "MIT" - }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/nodejs/package.json b/nodejs/package.json deleted file mode 100644 index 48003c6..0000000 --- a/nodejs/package.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "name": "@jbride/bitcoinpqc", - "version": "0.2.9", - "description": "NodeJS TypeScript bindings for Bitcoin PQC library", - "main": "dist/index.js", - "types": "dist/index.d.ts", - "scripts": { - "sync-c-sources": "./scripts/sync-c-sources.sh", - "build": "npm run sync-c-sources && tsc -p . && node-gyp rebuild", - "install": "node-gyp rebuild", - "test": "jest", - "prepare": "npm run build", - "examples": "ts-node examples/basic-usage.ts" - }, - "keywords": [ - "bitcoin", - "cryptocurrency", - "post-quantum", - "cryptography", - "signature", - "dilithium", - "sphincs+" - ], - "author": "Hunter Beast ", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/bitcoin/libbitcoinpqc.git", - "directory": "nodejs" - }, - "bugs": { - "url": "https://github.com/bitcoin/libbitcoinpqc/issues" - }, - "homepage": "https://github.com/bitcoin/libbitcoinpqc#readme", - "type": "commonjs", - "devDependencies": { - "@types/jest": "^29.5.12", - "@types/node": "^20.11.30", - "jest": "^29.7.0", - "ts-jest": "^29.1.2", - "ts-node": "^10.9.2", - "typescript": "^5.4.2", - "node-gyp": "^9.0.0" - }, - "dependencies": { - "node-addon-api": "^5.0.0" - }, - "files": [ - "dist", - "README.md", - "binding.gyp", - "tsconfig.json", - "src/native", - "src/c_sources" - ], - "gypfile": true, - "publishConfig": { - "access": "public" - } -} diff --git a/nodejs/scripts/sync-c-sources.sh b/nodejs/scripts/sync-c-sources.sh deleted file mode 100755 index c1b673d..0000000 --- a/nodejs/scripts/sync-c-sources.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -# Script to sync C source files from parent directory to src/c_sources -# This should be run before building or publishing the package - -set -e - -echo "Syncing C source files..." - -# Remove existing c_sources directory -rm -rf src/c_sources - -# Create new c_sources directory -mkdir -p src/c_sources - -# Copy C source files -echo "Copying main C source file..." -cp ../src/bitcoinpqc.c src/c_sources/ - -echo "Copying ML-DSA source files..." -cp -r ../src/ml_dsa src/c_sources/ - -echo "Copying SLH-DSA source files..." -cp -r ../src/slh_dsa src/c_sources/ - -echo "Copying Dilithium reference implementation..." -cp -r ../dilithium/ref src/c_sources/dilithium_ref - -echo "Copying SPHINCS+ reference implementation..." -cp -r ../sphincsplus/ref src/c_sources/sphincsplus_ref - -echo "Copying include files..." -cp -r ../include src/c_sources/ - -# Update include paths in C source files -echo "Updating include paths..." -find src/c_sources -name "*.c" -exec sed -i 's|../../dilithium/ref/|../dilithium_ref/|g' {} \; -find src/c_sources -name "*.c" -exec sed -i 's|../../sphincsplus/ref/|../sphincsplus_ref/|g' {} \; -find src/c_sources -name "*.c" -exec sed -i 's|../../include/|../include/|g' {} \; - -echo "C source files synced successfully!" \ No newline at end of file diff --git a/nodejs/src/__tests__/bitcoinpqc.test.ts b/nodejs/src/__tests__/bitcoinpqc.test.ts deleted file mode 100644 index 54f7c7c..0000000 --- a/nodejs/src/__tests__/bitcoinpqc.test.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { - Algorithm, - ErrorCode, - PqcError, - generateKeyPair, - publicKeySize, - secretKeySize, - sign, - signatureSize, - verify, -} from "../index"; - -import { getLibrary, setLibraryForTesting, BitcoinPqcNative } from "../library"; - -describe("Bitcoin PQC", () => { - // Generate random data for tests - function getRandomBytes(size: number): Uint8Array { - const bytes = new Uint8Array(size); - for (let i = 0; i < size; i++) { - bytes[i] = Math.floor(Math.random() * 256); - } - return bytes; - } - - describe("key sizes", () => { - test("should report correct key sizes for each algorithm", () => { - // Test key size reporting functions - for (const algo of [ - Algorithm.SECP256K1_SCHNORR, - Algorithm.ML_DSA_44, - Algorithm.SLH_DSA_SHAKE_128S, - ]) { - expect(publicKeySize(algo)).toBeGreaterThan(0); - expect(secretKeySize(algo)).toBeGreaterThan(0); - expect(signatureSize(algo)).toBeGreaterThan(0); - } - }); - }); - - describe("ML-DSA-44 (Dilithium)", () => { - const algorithm = Algorithm.ML_DSA_44; - - // Skip this test for now - test.skip("should generate keypair, sign and verify", () => { - // Generate random data for key generation - const randomData = getRandomBytes(128); - - // Generate a keypair - const keypair = generateKeyPair(algorithm, randomData); - - // Verify key sizes match reported sizes - expect(keypair.publicKey.bytes.length).toBe(publicKeySize(algorithm)); - expect(keypair.secretKey.bytes.length).toBe(secretKeySize(algorithm)); - - // Test message signing - const message = new TextEncoder().encode("Hello, Bitcoin PQC!"); - const signature = sign(keypair.secretKey, message); - - // Verify signature size matches reported size - expect(signature.bytes.length).toBe(signatureSize(algorithm)); - - // Verify the signature - should not throw - expect(() => { - verify(keypair.publicKey, message, signature); - }).not.toThrow(); - - // Verify with raw signature bytes - expect(() => { - verify(keypair.publicKey, message, signature.bytes); - }).not.toThrow(); - - // Verify that the signature doesn't verify for a different message - const badMessage = new TextEncoder().encode("Bad message!"); - expect(() => { - verify(keypair.publicKey, badMessage, signature); - }).toThrow(PqcError); - }); - }); - - describe("SLH-DSA-SHAKE-128s (SPHINCS+)", () => { - const algorithm = Algorithm.SLH_DSA_SHAKE_128S; - - test("should generate keypair, sign and verify", () => { - // Generate random data for key generation - const randomData = getRandomBytes(128); - - // Generate a keypair - const keypair = generateKeyPair(algorithm, randomData); - - // Verify key sizes match reported sizes - expect(keypair.publicKey.bytes.length).toBe(publicKeySize(algorithm)); - expect(keypair.secretKey.bytes.length).toBe(secretKeySize(algorithm)); - - // Test message signing - const message = new TextEncoder().encode("Hello, Bitcoin PQC!"); - const signature = sign(keypair.secretKey, message); - - // Verify signature size matches reported size - expect(signature.bytes.length).toBe(signatureSize(algorithm)); - - // Verify the signature - should not throw - expect(() => { - verify(keypair.publicKey, message, signature); - }).not.toThrow(); - }); - }); - - - test("should generate keypair, sign and verify", () => { - // Generate random data for key generation - const randomData = getRandomBytes(128); - - // Generate a keypair - const keypair = generateKeyPair(algorithm, randomData); - - // Verify key sizes match reported sizes - expect(keypair.publicKey.bytes.length).toBe(publicKeySize(algorithm)); - expect(keypair.secretKey.bytes.length).toBe(secretKeySize(algorithm)); - - // Test message signing - const message = new TextEncoder().encode("Hello, Bitcoin PQC!"); - const signature = sign(keypair.secretKey, message); - - // Verify signature size matches reported size - expect(signature.bytes.length).toBe(signatureSize(algorithm)); - - // Verify the signature - should not throw - expect(() => { - verify(keypair.publicKey, message, signature); - }).not.toThrow(); - }); -}); - -describe("error conditions", () => { - test("should throw on invalid input", () => { - // Invalid algorithm - expect(() => { - const randomData = getRandomBytes(128); - generateKeyPair(99 as Algorithm, randomData); - }).toThrow(PqcError); - - // Invalid random data size - expect(() => { - const randomData = getRandomBytes(16); // Less than 128 bytes - generateKeyPair(Algorithm.ML_DSA_44, randomData); - }).toThrow(PqcError); - }); -}); -}); diff --git a/nodejs/src/index.ts b/nodejs/src/index.ts deleted file mode 100644 index 9cd2577..0000000 --- a/nodejs/src/index.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { getLibrary } from "./library"; -import { - Algorithm, - ErrorCode, - KeyPair, - PqcError, - PublicKey, - SecretKey, - Signature, -} from "./types"; - -// Re-export types -export { - Algorithm, - ErrorCode, - KeyPair, - PqcError, - PublicKey, - SecretKey, - Signature, -}; - -/** - * Get the public key size for an algorithm - * - * @param algorithm - The algorithm identifier - * @returns The public key size in bytes - */ -export function publicKeySize(algorithm: Algorithm): number { - return getLibrary().bitcoin_pqc_public_key_size(algorithm); -} - -/** - * Get the secret key size for an algorithm - * - * @param algorithm - The algorithm identifier - * @returns The secret key size in bytes - */ -export function secretKeySize(algorithm: Algorithm): number { - return getLibrary().bitcoin_pqc_secret_key_size(algorithm); -} - -/** - * Get the signature size for an algorithm - * - * @param algorithm - The algorithm identifier - * @returns The signature size in bytes - */ -export function signatureSize(algorithm: Algorithm): number { - return getLibrary().bitcoin_pqc_signature_size(algorithm); -} - -/** - * Generate a key pair for the specified algorithm - * - * @param algorithm - The PQC algorithm to use - * @param randomData - Random bytes for key generation (must be at least 128 bytes) - * @returns A new key pair - * @throws {PqcError} If key generation fails - */ -export function generateKeyPair( - algorithm: Algorithm, - randomData: Uint8Array -): KeyPair { - if (!(randomData instanceof Uint8Array)) { - throw new PqcError( - ErrorCode.BAD_ARGUMENT, - "Random data must be a Uint8Array" - ); - } - - if (randomData.length < 128) { - throw new PqcError( - ErrorCode.BAD_ARGUMENT, - "Random data must be at least 128 bytes" - ); - } - - const lib = getLibrary(); - const result = lib.bitcoin_pqc_keygen(algorithm, randomData); - - if (result.resultCode !== ErrorCode.OK) { - throw new PqcError(result.resultCode); - } - - const publicKey = new PublicKey(algorithm, result.publicKey); - const secretKey = new SecretKey(algorithm, result.secretKey); - - return new KeyPair(publicKey, secretKey); -} - -/** - * Sign a message using the specified secret key - * - * @param secretKey - The secret key to sign with - * @param message - The message to sign - * @returns A signature - * @throws {PqcError} If signing fails - */ -export function sign(secretKey: SecretKey, message: Uint8Array): Signature { - if (!(secretKey instanceof SecretKey)) { - throw new PqcError( - ErrorCode.BAD_ARGUMENT, - "Secret key must be a SecretKey instance" - ); - } - - if (!(message instanceof Uint8Array)) { - throw new PqcError(ErrorCode.BAD_ARGUMENT, "Message must be a Uint8Array"); - } - - const lib = getLibrary(); - const result = lib.bitcoin_pqc_sign( - secretKey.algorithm, - secretKey.bytes, - message - ); - - if (result.resultCode !== ErrorCode.OK) { - throw new PqcError(result.resultCode); - } - - return new Signature(secretKey.algorithm, result.signature); -} - -/** - * Verify a signature using the specified public key - * - * @param publicKey - The public key to verify with - * @param message - The message that was signed - * @param signature - The signature to verify - * @returns {void} - * @throws {PqcError} If verification fails - */ -export function verify( - publicKey: PublicKey, - message: Uint8Array, - signature: Signature | Uint8Array -): void { - if (!(publicKey instanceof PublicKey)) { - throw new PqcError( - ErrorCode.BAD_ARGUMENT, - "Public key must be a PublicKey instance" - ); - } - - if (!(message instanceof Uint8Array)) { - throw new PqcError(ErrorCode.BAD_ARGUMENT, "Message must be a Uint8Array"); - } - - const lib = getLibrary(); - const sigBytes = signature instanceof Signature ? signature.bytes : signature; - - if (!(sigBytes instanceof Uint8Array)) { - throw new PqcError( - ErrorCode.BAD_ARGUMENT, - "Signature must be a Signature or Uint8Array instance" - ); - } - - const result = lib.bitcoin_pqc_verify( - publicKey.algorithm, - publicKey.bytes, - message, - sigBytes - ); - - if (result !== ErrorCode.OK) { - throw new PqcError(result); - } -} diff --git a/nodejs/src/library.ts b/nodejs/src/library.ts deleted file mode 100644 index 4b75517..0000000 --- a/nodejs/src/library.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { join } from "path"; -import { existsSync } from "fs"; -import { Algorithm, ErrorCode } from "./types"; - -// Try to load the native addon -let nativeAddon: any = null; -try { - nativeAddon = require("../build/Release/bitcoinpqc"); - console.log("Loaded native addon successfully"); -} catch (error) { - console.warn("Failed to load native addon:", error); -} - -// Define functions from the native library -export interface BitcoinPqcNative { - // Size information - bitcoin_pqc_public_key_size(algorithm: number): number; - bitcoin_pqc_secret_key_size(algorithm: number): number; - bitcoin_pqc_signature_size(algorithm: number): number; - - // Key generation, signing and verification - bitcoin_pqc_keygen( - algorithm: number, - randomData: Uint8Array - ): { publicKey: Uint8Array; secretKey: Uint8Array; resultCode: number }; - - bitcoin_pqc_sign( - algorithm: number, - secretKey: Uint8Array, - message: Uint8Array - ): { signature: Uint8Array; resultCode: number }; - - bitcoin_pqc_verify( - algorithm: number, - publicKey: Uint8Array, - message: Uint8Array, - signature: Uint8Array - ): number; -} - -interface KeySizeConfig { - publicKey: number; - secretKey: number; - signature: number; -} - -// Mock library implementation as fallback -class MockBitcoinPqcNative implements BitcoinPqcNative { - // These values are from the actual implementation - private keySizes: { [key: number]: KeySizeConfig } = { - [Algorithm.SECP256K1_SCHNORR]: { - publicKey: 32, - secretKey: 32, - signature: 64, - }, - [Algorithm.ML_DSA_44]: { - publicKey: 1312, - secretKey: 2528, - signature: 2420, - }, - [Algorithm.SLH_DSA_SHAKE_128S]: { - publicKey: 32, - secretKey: 64, - signature: 7856, - }, - }; - - bitcoin_pqc_public_key_size(algorithm: number): number { - return this.keySizes[algorithm]?.publicKey || 0; - } - - bitcoin_pqc_secret_key_size(algorithm: number): number { - return this.keySizes[algorithm]?.secretKey || 0; - } - - bitcoin_pqc_signature_size(algorithm: number): number { - return this.keySizes[algorithm]?.signature || 0; - } - - bitcoin_pqc_keygen( - algorithm: number, - randomData: Uint8Array - ): { publicKey: Uint8Array; secretKey: Uint8Array; resultCode: number } { - if (randomData.length < 128) { - return { - publicKey: new Uint8Array(0), - secretKey: new Uint8Array(0), - resultCode: ErrorCode.BAD_ARGUMENT, - }; - } - - if (algorithm < 0 || algorithm > 3) { - return { - publicKey: new Uint8Array(0), - secretKey: new Uint8Array(0), - resultCode: ErrorCode.BAD_ARGUMENT, - }; - } - - const pkSize = this.bitcoin_pqc_public_key_size(algorithm); - const skSize = this.bitcoin_pqc_secret_key_size(algorithm); - - // In a real implementation, this would call the native library - // Here we're just creating dummy keys based on the random data - const publicKey = new Uint8Array(pkSize); - const secretKey = new Uint8Array(skSize); - - // Use random data to populate the key - for (let i = 0; i < pkSize && i < randomData.length; i++) { - publicKey[i] = randomData[i]; - } - - for (let i = 0; i < skSize && i < randomData.length; i++) { - secretKey[i] = randomData[i + Math.floor(randomData.length / 2)]; - } - - return { publicKey, secretKey, resultCode: ErrorCode.OK }; - } - - bitcoin_pqc_sign( - algorithm: number, - secretKey: Uint8Array, - message: Uint8Array - ): { signature: Uint8Array; resultCode: number } { - if (algorithm < 0 || algorithm > 3) { - return { - signature: new Uint8Array(0), - resultCode: ErrorCode.BAD_ARGUMENT, - }; - } - - const expectedSize = this.bitcoin_pqc_secret_key_size(algorithm); - if (secretKey.length !== expectedSize) { - return { signature: new Uint8Array(0), resultCode: ErrorCode.BAD_KEY }; - } - - const sigSize = this.bitcoin_pqc_signature_size(algorithm); - const signature = new Uint8Array(sigSize); - - // In a real implementation, this would call the native library - // Here we're just creating a dummy signature - // In reality, this would be a deterministic signature based on the message and secret key - for (let i = 0; i < sigSize; i++) { - signature[i] = i < message.length ? message[i] : 0; - } - - return { signature, resultCode: ErrorCode.OK }; - } - - bitcoin_pqc_verify( - algorithm: number, - publicKey: Uint8Array, - message: Uint8Array, - signature: Uint8Array - ): number { - if (algorithm < 0 || algorithm > 3) { - return ErrorCode.BAD_ARGUMENT; - } - - const expectedPkSize = this.bitcoin_pqc_public_key_size(algorithm); - if (publicKey.length !== expectedPkSize) { - return ErrorCode.BAD_KEY; - } - - const expectedSigSize = this.bitcoin_pqc_signature_size(algorithm); - if (signature.length !== expectedSigSize) { - return ErrorCode.BAD_SIGNATURE; - } - - // In a real implementation, this would verify the signature - // Here we're just pretending it's valid - return ErrorCode.OK; - } -} - -// Fall back to mock implementation if native addon is not available -const addonOrMock = nativeAddon || new MockBitcoinPqcNative(); - -// Get the library instance -export function getLibrary(): BitcoinPqcNative { - return addonOrMock; -} - -// For testing - allow library to be replaced -export function setLibraryForTesting(mockLib: BitcoinPqcNative): void { - nativeAddon = mockLib; -} diff --git a/nodejs/src/native/bitcoinpqc_addon.cc b/nodejs/src/native/bitcoinpqc_addon.cc deleted file mode 100644 index b8e9c43..0000000 --- a/nodejs/src/native/bitcoinpqc_addon.cc +++ /dev/null @@ -1,208 +0,0 @@ -#include -#include - -/** - * Get the public key size for an algorithm - */ -Napi::Value GetPublicKeySize(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 1 || !info[0].IsNumber()) { - Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - size_t size = bitcoin_pqc_public_key_size(static_cast(algorithm)); - - return Napi::Number::New(env, static_cast(size)); -} - -/** - * Get the secret key size for an algorithm - */ -Napi::Value GetSecretKeySize(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 1 || !info[0].IsNumber()) { - Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - size_t size = bitcoin_pqc_secret_key_size(static_cast(algorithm)); - - return Napi::Number::New(env, static_cast(size)); -} - -/** - * Get the signature size for an algorithm - */ -Napi::Value GetSignatureSize(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 1 || !info[0].IsNumber()) { - Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - size_t size = bitcoin_pqc_signature_size(static_cast(algorithm)); - - return Napi::Number::New(env, static_cast(size)); -} - -/** - * Generate a key pair - */ -Napi::Value GenerateKeypair(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsTypedArray()) { - Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - Napi::Uint8Array randomData = info[1].As(); - - if (randomData.ByteLength() < 128) { - Napi::Error::New(env, "Random data must be at least 128 bytes").ThrowAsJavaScriptException(); - return env.Null(); - } - - // Set up keypair struct - bitcoin_pqc_keypair_t keypair; - bitcoin_pqc_error_t result = bitcoin_pqc_keygen( - static_cast(algorithm), - &keypair, - randomData.Data(), - randomData.ByteLength() - ); - - // Create result object - Napi::Object returnValue = Napi::Object::New(env); - - // Check for errors - if (result != BITCOIN_PQC_OK) { - returnValue.Set("resultCode", Napi::Number::New(env, static_cast(result))); - returnValue.Set("publicKey", Napi::Uint8Array::New(env, 0)); - returnValue.Set("secretKey", Napi::Uint8Array::New(env, 0)); - return returnValue; - } - - // Copy public key - Napi::Uint8Array publicKey = Napi::Uint8Array::New(env, keypair.public_key_size); - memcpy(publicKey.Data(), keypair.public_key, keypair.public_key_size); - returnValue.Set("publicKey", publicKey); - - // Copy secret key - Napi::Uint8Array secretKey = Napi::Uint8Array::New(env, keypair.secret_key_size); - memcpy(secretKey.Data(), keypair.secret_key, keypair.secret_key_size); - returnValue.Set("secretKey", secretKey); - - // Set result code - returnValue.Set("resultCode", Napi::Number::New(env, 0)); // BITCOIN_PQC_OK - - // Clean up - bitcoin_pqc_keypair_free(&keypair); - - return returnValue; -} - -/** - * Sign a message - */ -Napi::Value SignMessage(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 3 || !info[0].IsNumber() || !info[1].IsTypedArray() || !info[2].IsTypedArray()) { - Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - Napi::Uint8Array secretKey = info[1].As(); - Napi::Uint8Array message = info[2].As(); - - // Set up signature struct - bitcoin_pqc_signature_t signature; - bitcoin_pqc_error_t result = bitcoin_pqc_sign( - static_cast(algorithm), - secretKey.Data(), - secretKey.ByteLength(), - message.Data(), - message.ByteLength(), - &signature - ); - - // Create result object - Napi::Object returnValue = Napi::Object::New(env); - - // Check for errors - if (result != BITCOIN_PQC_OK) { - returnValue.Set("resultCode", Napi::Number::New(env, static_cast(result))); - returnValue.Set("signature", Napi::Uint8Array::New(env, 0)); - return returnValue; - } - - // Copy signature - Napi::Uint8Array signatureData = Napi::Uint8Array::New(env, signature.signature_size); - memcpy(signatureData.Data(), signature.signature, signature.signature_size); - returnValue.Set("signature", signatureData); - - // Set result code - returnValue.Set("resultCode", Napi::Number::New(env, 0)); // BITCOIN_PQC_OK - - // Clean up - bitcoin_pqc_signature_free(&signature); - - return returnValue; -} - -/** - * Verify a signature - */ -Napi::Value VerifySignature(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 4 || !info[0].IsNumber() || !info[1].IsTypedArray() || - !info[2].IsTypedArray() || !info[3].IsTypedArray()) { - Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - Napi::Uint8Array publicKey = info[1].As(); - Napi::Uint8Array message = info[2].As(); - Napi::Uint8Array signature = info[3].As(); - - // Verify signature - bitcoin_pqc_error_t result = bitcoin_pqc_verify( - static_cast(algorithm), - publicKey.Data(), - publicKey.ByteLength(), - message.Data(), - message.ByteLength(), - signature.Data(), - signature.ByteLength() - ); - - // Return result code - return Napi::Number::New(env, static_cast(result)); -} - -/** - * Initialize the module - */ -Napi::Object Init(Napi::Env env, Napi::Object exports) { - exports.Set("bitcoin_pqc_public_key_size", Napi::Function::New(env, GetPublicKeySize)); - exports.Set("bitcoin_pqc_secret_key_size", Napi::Function::New(env, GetSecretKeySize)); - exports.Set("bitcoin_pqc_signature_size", Napi::Function::New(env, GetSignatureSize)); - exports.Set("bitcoin_pqc_keygen", Napi::Function::New(env, GenerateKeypair)); - exports.Set("bitcoin_pqc_sign", Napi::Function::New(env, SignMessage)); - exports.Set("bitcoin_pqc_verify", Napi::Function::New(env, VerifySignature)); - return exports; -} - -NODE_API_MODULE(bitcoinpqc, Init) diff --git a/nodejs/src/native/bitcoinpqc_wrapper.cc b/nodejs/src/native/bitcoinpqc_wrapper.cc deleted file mode 100644 index 5bfa4b7..0000000 --- a/nodejs/src/native/bitcoinpqc_wrapper.cc +++ /dev/null @@ -1,171 +0,0 @@ -#include "bitcoinpqc_wrapper.h" - -Napi::Value GetPublicKeySize(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 1 || !info[0].IsNumber()) { - Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - size_t size = bitcoin_pqc_public_key_size(static_cast(algorithm)); - - return Napi::Number::New(env, static_cast(size)); -} - -Napi::Value GetSecretKeySize(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 1 || !info[0].IsNumber()) { - Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - size_t size = bitcoin_pqc_secret_key_size(static_cast(algorithm)); - - return Napi::Number::New(env, static_cast(size)); -} - -Napi::Value GetSignatureSize(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 1 || !info[0].IsNumber()) { - Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - size_t size = bitcoin_pqc_signature_size(static_cast(algorithm)); - - return Napi::Number::New(env, static_cast(size)); -} - -Napi::Value GenerateKeypair(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsTypedArray()) { - Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - Napi::Uint8Array randomData = info[1].As(); - - if (randomData.ByteLength() < 128) { - Napi::Error::New(env, "Random data must be at least 128 bytes").ThrowAsJavaScriptException(); - return env.Null(); - } - - // Set up keypair struct - bitcoin_pqc_keypair_t keypair; - bitcoin_pqc_error_t result = bitcoin_pqc_keygen( - static_cast(algorithm), - &keypair, - randomData.Data(), - randomData.ByteLength() - ); - - // Check for errors - if (result != BITCOIN_PQC_OK) { - Napi::Error::New(env, "Key generation failed").ThrowAsJavaScriptException(); - return env.Null(); - } - - // Create result object - Napi::Object returnValue = Napi::Object::New(env); - - // Copy public key - Napi::Uint8Array publicKey = Napi::Uint8Array::New(env, keypair.public_key_size); - memcpy(publicKey.Data(), keypair.public_key, keypair.public_key_size); - returnValue.Set("publicKey", publicKey); - - // Copy secret key - Napi::Uint8Array secretKey = Napi::Uint8Array::New(env, keypair.secret_key_size); - memcpy(secretKey.Data(), keypair.secret_key, keypair.secret_key_size); - returnValue.Set("secretKey", secretKey); - - // Set result code - returnValue.Set("resultCode", Napi::Number::New(env, static_cast(result))); - - // Clean up - bitcoin_pqc_keypair_free(&keypair); - - return returnValue; -} - -Napi::Value SignMessage(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 3 || !info[0].IsNumber() || !info[1].IsTypedArray() || !info[2].IsTypedArray()) { - Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - Napi::Uint8Array secretKey = info[1].As(); - Napi::Uint8Array message = info[2].As(); - - // Set up signature struct - bitcoin_pqc_signature_t signature; - bitcoin_pqc_error_t result = bitcoin_pqc_sign( - static_cast(algorithm), - secretKey.Data(), - secretKey.ByteLength(), - message.Data(), - message.ByteLength(), - &signature - ); - - // Check for errors - if (result != BITCOIN_PQC_OK) { - Napi::Error::New(env, "Signing failed").ThrowAsJavaScriptException(); - return env.Null(); - } - - // Create result object - Napi::Object returnValue = Napi::Object::New(env); - - // Copy signature - Napi::Uint8Array signatureData = Napi::Uint8Array::New(env, signature.signature_size); - memcpy(signatureData.Data(), signature.signature, signature.signature_size); - returnValue.Set("signature", signatureData); - - // Set result code - returnValue.Set("resultCode", Napi::Number::New(env, static_cast(result))); - - // Clean up - bitcoin_pqc_signature_free(&signature); - - return returnValue; -} - -Napi::Value VerifySignature(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - if (info.Length() < 4 || !info[0].IsNumber() || !info[1].IsTypedArray() || - !info[2].IsTypedArray() || !info[3].IsTypedArray()) { - Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - Napi::Uint8Array publicKey = info[1].As(); - Napi::Uint8Array message = info[2].As(); - Napi::Uint8Array signature = info[3].As(); - - // Verify signature - bitcoin_pqc_error_t result = bitcoin_pqc_verify( - static_cast(algorithm), - publicKey.Data(), - publicKey.ByteLength(), - message.Data(), - message.ByteLength(), - signature.Data(), - signature.ByteLength() - ); - - // Return result code - return Napi::Number::New(env, static_cast(result)); -} diff --git a/nodejs/src/native/bitcoinpqc_wrapper.h b/nodejs/src/native/bitcoinpqc_wrapper.h deleted file mode 100644 index ff7b4b2..0000000 --- a/nodejs/src/native/bitcoinpqc_wrapper.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef BITCOINPQC_WRAPPER_H -#define BITCOINPQC_WRAPPER_H - -#include -#include - -// Key size functions -Napi::Value GetPublicKeySize(const Napi::CallbackInfo& info); -Napi::Value GetSecretKeySize(const Napi::CallbackInfo& info); -Napi::Value GetSignatureSize(const Napi::CallbackInfo& info); - -// Key generation, signing and verification -Napi::Value GenerateKeypair(const Napi::CallbackInfo& info); -Napi::Value SignMessage(const Napi::CallbackInfo& info); -Napi::Value VerifySignature(const Napi::CallbackInfo& info); - -#endif diff --git a/nodejs/src/native/mock_bitcoinpqc_addon.cc b/nodejs/src/native/mock_bitcoinpqc_addon.cc deleted file mode 100644 index 9332cc8..0000000 --- a/nodejs/src/native/mock_bitcoinpqc_addon.cc +++ /dev/null @@ -1,305 +0,0 @@ -#include -#include - -// Mock key sizes -const int SECP256K1_PK_SIZE = 32; -const int SECP256K1_SK_SIZE = 32; -const int SECP256K1_SIG_SIZE = 64; - -const int ML_DSA_44_PK_SIZE = 1312; -const int ML_DSA_44_SK_SIZE = 2528; -const int ML_DSA_44_SIG_SIZE = 2420; - -const int SLH_DSA_SHAKE_128S_PK_SIZE = 32; -const int SLH_DSA_SHAKE_128S_SK_SIZE = 64; -const int SLH_DSA_SHAKE_128S_SIG_SIZE = 7856; - -// Error codes -const int OK = 0; -const int BAD_ARGUMENT = -1; -const int BAD_KEY = -2; -const int BAD_SIGNATURE = -3; -const int NOT_IMPLEMENTED = -4; - -Napi::Value GetPublicKeySize(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - - if (info.Length() < 1 || !info[0].IsNumber()) { - Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - - int size = 0; - switch (algorithm) { - case 0: - size = SECP256K1_PK_SIZE; - break; - case 1: - size = ML_DSA_44_PK_SIZE; - break; - case 2: - size = SLH_DSA_SHAKE_128S_PK_SIZE; - break; - default: - size = 0; - } - - return Napi::Number::New(env, size); -} - -Napi::Value GetSecretKeySize(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - - if (info.Length() < 1 || !info[0].IsNumber()) { - Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - - int size = 0; - switch (algorithm) { - case 0: - size = SECP256K1_SK_SIZE; - break; - case 1: - size = ML_DSA_44_SK_SIZE; - break; - case 2: - size = SLH_DSA_SHAKE_128S_SK_SIZE; - break; - default: - size = 0; - } - - return Napi::Number::New(env, size); -} - -Napi::Value GetSignatureSize(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - - if (info.Length() < 1 || !info[0].IsNumber()) { - Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - - int size = 0; - switch (algorithm) { - case 0: - size = SECP256K1_SIG_SIZE; - break; - case 1: - size = ML_DSA_44_SIG_SIZE; - break; - case 2: - size = SLH_DSA_SHAKE_128S_SIG_SIZE; - break; - default: - size = 0; - } - - return Napi::Number::New(env, size); -} - -Napi::Value GenerateKeypair(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - - if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsTypedArray()) { - Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - Napi::Uint8Array randomData = info[1].As(); - - if (randomData.ByteLength() < 128) { - Napi::Error::New(env, "Random data must be at least 128 bytes") - .ThrowAsJavaScriptException(); - return env.Null(); - } - - if (algorithm < 0 || algorithm > 3) { - Napi::Error::New(env, "Invalid algorithm").ThrowAsJavaScriptException(); - return env.Null(); - } - - // Get key sizes - int pkSize = 0; - int skSize = 0; - - switch (algorithm) { - case 0: - pkSize = SECP256K1_PK_SIZE; - skSize = SECP256K1_SK_SIZE; - break; - case 1: - pkSize = ML_DSA_44_PK_SIZE; - skSize = ML_DSA_44_SK_SIZE; - break; - case 2: - pkSize = SLH_DSA_SHAKE_128S_PK_SIZE; - skSize = SLH_DSA_SHAKE_128S_SK_SIZE; - break; - default: - return Napi::Number::New(env, BAD_ARGUMENT); - } - - // Create result object - Napi::Object result = Napi::Object::New(env); - - // Create dummy keys - Napi::Uint8Array publicKey = Napi::Uint8Array::New(env, pkSize); - Napi::Uint8Array secretKey = Napi::Uint8Array::New(env, skSize); - - // Use random data to fill the keys - for (size_t i = 0; i < pkSize && i < randomData.ByteLength(); i++) { - publicKey[i] = randomData[i]; - } - - for (size_t i = 0; i < skSize && i < randomData.ByteLength(); i++) { - secretKey[i] = randomData[i + randomData.ByteLength() / 2]; - } - - result.Set("publicKey", publicKey); - result.Set("secretKey", secretKey); - result.Set("resultCode", OK); - - return result; -} - -Napi::Value SignMessage(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - - if (info.Length() < 3 || !info[0].IsNumber() || !info[1].IsTypedArray() || - !info[2].IsTypedArray()) { - Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - Napi::Uint8Array secretKey = info[1].As(); - Napi::Uint8Array message = info[2].As(); - - if (algorithm < 0 || algorithm > 3) { - Napi::Error::New(env, "Invalid algorithm").ThrowAsJavaScriptException(); - return env.Null(); - } - - // Get expected signature size - int sigSize = 0; - int expectedSkSize = 0; - - switch (algorithm) { - case 0: - sigSize = SECP256K1_SIG_SIZE; - expectedSkSize = SECP256K1_SK_SIZE; - break; - case 1: - sigSize = ML_DSA_44_SIG_SIZE; - expectedSkSize = ML_DSA_44_SK_SIZE; - break; - case 2: - sigSize = SLH_DSA_SHAKE_128S_SIG_SIZE; - expectedSkSize = SLH_DSA_SHAKE_128S_SK_SIZE; - break; - default: - return Napi::Number::New(env, BAD_ARGUMENT); - } - - // Check key size - if (secretKey.ByteLength() != expectedSkSize) { - Napi::Object result = Napi::Object::New(env); - result.Set("signature", Napi::Uint8Array::New(env, 0)); - result.Set("resultCode", BAD_KEY); - return result; - } - - // Create result object - Napi::Object result = Napi::Object::New(env); - - // Create dummy signature - Napi::Uint8Array signature = Napi::Uint8Array::New(env, sigSize); - - // Use message to fill the signature (in a real implementation this would be a - // proper signature) - for (size_t i = 0; i < sigSize; i++) { - signature[i] = i < message.ByteLength() ? message[i] : 0; - } - - result.Set("signature", signature); - result.Set("resultCode", OK); - - return result; -} - -Napi::Value VerifySignature(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - - if (info.Length() < 4 || !info[0].IsNumber() || !info[1].IsTypedArray() || - !info[2].IsTypedArray() || !info[3].IsTypedArray()) { - Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); - return env.Null(); - } - - int algorithm = info[0].As().Int32Value(); - Napi::Uint8Array publicKey = info[1].As(); - Napi::Uint8Array message = info[2].As(); - Napi::Uint8Array signature = info[3].As(); - - if (algorithm < 0 || algorithm > 3) { - return Napi::Number::New(env, BAD_ARGUMENT); - } - - // Get expected key and signature sizes - int expectedPkSize = 0; - int expectedSigSize = 0; - - switch (algorithm) { - case 0: - expectedPkSize = SECP256K1_PK_SIZE; - expectedSigSize = SECP256K1_SIG_SIZE; - break; - case 1: - expectedPkSize = ML_DSA_44_PK_SIZE; - expectedSigSize = ML_DSA_44_SIG_SIZE; - break; - case 2: - expectedPkSize = SLH_DSA_SHAKE_128S_PK_SIZE; - expectedSigSize = SLH_DSA_SHAKE_128S_SIG_SIZE; - break; - default: - return Napi::Number::New(env, BAD_ARGUMENT); - } - - // Check key and signature sizes - if (publicKey.ByteLength() != expectedPkSize) { - return Napi::Number::New(env, BAD_KEY); - } - - if (signature.ByteLength() != expectedSigSize) { - return Napi::Number::New(env, BAD_SIGNATURE); - } - - // In a real implementation, this would verify the signature - // Here we're just pretending it's valid - return Napi::Number::New(env, OK); -} - -Napi::Object Init(Napi::Env env, Napi::Object exports) { - exports.Set("bitcoin_pqc_public_key_size", - Napi::Function::New(env, GetPublicKeySize)); - exports.Set("bitcoin_pqc_secret_key_size", - Napi::Function::New(env, GetSecretKeySize)); - exports.Set("bitcoin_pqc_signature_size", - Napi::Function::New(env, GetSignatureSize)); - exports.Set("bitcoin_pqc_keygen", Napi::Function::New(env, GenerateKeypair)); - exports.Set("bitcoin_pqc_sign", Napi::Function::New(env, SignMessage)); - exports.Set("bitcoin_pqc_verify", Napi::Function::New(env, VerifySignature)); - return exports; -} - -NODE_API_MODULE(mock_bitcoinpqc, Init) diff --git a/nodejs/src/types.ts b/nodejs/src/types.ts deleted file mode 100644 index 282c408..0000000 --- a/nodejs/src/types.ts +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Bitcoin PQC algorithm identifiers - */ -export enum Algorithm { - /** BIP-340 Schnorr + X-Only - Elliptic Curve Digital Signature Algorithm */ - SECP256K1_SCHNORR = 0, - /** ML-DSA-44 (CRYSTALS-Dilithium) - Lattice-based signature scheme */ - ML_DSA_44 = 1, - /** SLH-DSA-Shake-128s (SPHINCS+) - Hash-based signature scheme */ - SLH_DSA_SHAKE_128S = 2, -} - -/** - * Error types for PQC operations - */ -export enum ErrorCode { - /** Operation completed successfully */ - OK = 0, - /** Invalid arguments provided */ - BAD_ARGUMENT = -1, - /** Invalid key provided */ - BAD_KEY = -2, - /** Invalid signature provided */ - BAD_SIGNATURE = -3, - /** Algorithm not implemented */ - NOT_IMPLEMENTED = -4, -} - -/** - * Error class for PQC operations - */ -export class PqcError extends Error { - readonly code: ErrorCode; - - constructor(code: ErrorCode, message?: string) { - // Use a default message if none provided - const defaultMessage = (() => { - switch (code) { - case ErrorCode.BAD_ARGUMENT: - return "Invalid arguments provided"; - case ErrorCode.BAD_KEY: - return "Invalid key provided"; - case ErrorCode.BAD_SIGNATURE: - return "Invalid signature provided"; - case ErrorCode.NOT_IMPLEMENTED: - return "Algorithm not implemented"; - default: - return `Unexpected error code: ${code}`; - } - })(); - - super(message || defaultMessage); - this.code = code; - this.name = "PqcError"; - - // For better stack traces in Node.js - Error.captureStackTrace(this, PqcError); - } -} - -/** - * Public key wrapper - */ -export class PublicKey { - /** The algorithm this key belongs to */ - readonly algorithm: Algorithm; - /** The raw key bytes */ - readonly bytes: Uint8Array; - - constructor(algorithm: Algorithm, bytes: Uint8Array) { - this.algorithm = algorithm; - this.bytes = bytes; - } -} - -/** - * Secret key wrapper - */ -export class SecretKey { - /** The algorithm this key belongs to */ - readonly algorithm: Algorithm; - /** The raw key bytes */ - readonly bytes: Uint8Array; - - constructor(algorithm: Algorithm, bytes: Uint8Array) { - this.algorithm = algorithm; - this.bytes = bytes; - } -} - -/** - * Signature wrapper - */ -export class Signature { - /** The algorithm this signature belongs to */ - readonly algorithm: Algorithm; - /** The raw signature bytes */ - readonly bytes: Uint8Array; - - constructor(algorithm: Algorithm, bytes: Uint8Array) { - this.algorithm = algorithm; - this.bytes = bytes; - } -} - -/** - * Key pair containing both public and secret keys - */ -export class KeyPair { - /** The public key */ - readonly publicKey: PublicKey; - /** The secret key */ - readonly secretKey: SecretKey; - - constructor(publicKey: PublicKey, secretKey: SecretKey) { - if (publicKey.algorithm !== secretKey.algorithm) { - throw new PqcError( - ErrorCode.BAD_ARGUMENT, - "Public and secret key algorithms must match" - ); - } - this.publicKey = publicKey; - this.secretKey = secretKey; - } -} diff --git a/nodejs/tests/bitcoinpqc.test.ts b/nodejs/tests/bitcoinpqc.test.ts deleted file mode 100644 index 9930055..0000000 --- a/nodejs/tests/bitcoinpqc.test.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { - Algorithm, - ErrorCode, - PqcError, - generateKeyPair, - publicKeySize, - secretKeySize, - sign, - signatureSize, - verify, -} from "../src"; - -import { - getLibrary, - setLibraryForTesting, - BitcoinPqcNative, -} from "../src/library"; - -describe("Bitcoin PQC", () => { - // Generate random data for tests - function getRandomBytes(size: number): Uint8Array { - const bytes = new Uint8Array(size); - for (let i = 0; i < size; i++) { - bytes[i] = Math.floor(Math.random() * 256); - } - return bytes; - } - - describe("key sizes", () => { - test("should report correct key sizes for each algorithm", () => { - // Test key size reporting functions - for (const algo of [ - Algorithm.SECP256K1_SCHNORR, - Algorithm.ML_DSA_44, - Algorithm.SLH_DSA_SHAKE_128S, - ]) { - expect(publicKeySize(algo)).toBeGreaterThan(0); - expect(secretKeySize(algo)).toBeGreaterThan(0); - expect(signatureSize(algo)).toBeGreaterThan(0); - } - }); - }); - - describe("ML-DSA-44 (Dilithium)", () => { - const algorithm = Algorithm.ML_DSA_44; - - // Skip this test for now - test.skip("should generate keypair, sign and verify", () => { - // Generate random data for key generation - const randomData = getRandomBytes(128); - - // Generate a keypair - const keypair = generateKeyPair(algorithm, randomData); - - // Verify key sizes match reported sizes - expect(keypair.publicKey.bytes.length).toBe(publicKeySize(algorithm)); - expect(keypair.secretKey.bytes.length).toBe(secretKeySize(algorithm)); - - // Test message signing - const message = new TextEncoder().encode("Hello, Bitcoin PQC!"); - const signature = sign(keypair.secretKey, message); - - // Verify signature size matches reported size - expect(signature.bytes.length).toBe(signatureSize(algorithm)); - - // Verify the signature - should not throw - expect(() => { - verify(keypair.publicKey, message, signature); - }).not.toThrow(); - - // Verify with raw signature bytes - expect(() => { - verify(keypair.publicKey, message, signature.bytes); - }).not.toThrow(); - - // Verify that the signature doesn't verify for a different message - const badMessage = new TextEncoder().encode("Bad message!"); - expect(() => { - verify(keypair.publicKey, badMessage, signature); - }).toThrow(PqcError); - }); - }); - - describe("SLH-DSA-SHAKE-128s (SPHINCS+)", () => { - const algorithm = Algorithm.SLH_DSA_SHAKE_128S; - - test("should generate keypair, sign and verify", () => { - // Generate random data for key generation - const randomData = getRandomBytes(128); - - // Generate a keypair - const keypair = generateKeyPair(algorithm, randomData); - - // Verify key sizes match reported sizes - expect(keypair.publicKey.bytes.length).toBe(publicKeySize(algorithm)); - expect(keypair.secretKey.bytes.length).toBe(secretKeySize(algorithm)); - - // Test message signing - const message = new TextEncoder().encode("Hello, Bitcoin PQC!"); - const signature = sign(keypair.secretKey, message); - - // Verify signature size matches reported size - expect(signature.bytes.length).toBe(signatureSize(algorithm)); - - // Verify the signature - should not throw - expect(() => { - verify(keypair.publicKey, message, signature); - }).not.toThrow(); - }); - }); - - - test("should generate keypair, sign and verify", () => { - // Generate random data for key generation - const randomData = getRandomBytes(128); - - // Generate a keypair - const keypair = generateKeyPair(algorithm, randomData); - - // Verify key sizes match reported sizes - expect(keypair.publicKey.bytes.length).toBe(publicKeySize(algorithm)); - expect(keypair.secretKey.bytes.length).toBe(secretKeySize(algorithm)); - - // Test message signing - const message = new TextEncoder().encode("Hello, Bitcoin PQC!"); - const signature = sign(keypair.secretKey, message); - - // Verify signature size matches reported size - expect(signature.bytes.length).toBe(signatureSize(algorithm)); - - // Verify the signature - should not throw - expect(() => { - verify(keypair.publicKey, message, signature); - }).not.toThrow(); - }); -}); - -describe("error conditions", () => { - test("should throw on invalid input", () => { - // Invalid algorithm - expect(() => { - const randomData = getRandomBytes(128); - generateKeyPair(99 as Algorithm, randomData); - }).toThrow(PqcError); - - // Invalid random data size - expect(() => { - const randomData = getRandomBytes(16); // Less than 128 bytes - generateKeyPair(Algorithm.ML_DSA_44, randomData); - }).toThrow(PqcError); - }); -}); -}); diff --git a/nodejs/tsconfig.json b/nodejs/tsconfig.json deleted file mode 100644 index 7c2a087..0000000 --- a/nodejs/tsconfig.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - /* Language and Environment */ - "target": "es2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "libReplacement": true, /* Enable lib replacement. */ - // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ - "rootDir": "./src", /* Specify the root folder within your source files. */ - "baseUrl": ".", /* Specify the base directory to resolve non-relative module names. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ - // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */ - // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ - // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ - // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - /* Emit */ - "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./dist", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ - // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ - // "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - }, - "include": [ - "src/**/*.ts" - ], - "exclude": [ - "node_modules", - "**/*.test.ts", - "dist", - "src/__tests__/**/*", - "src/c_sources/**/*" - ] -} \ No newline at end of file diff --git a/python/MANIFEST.in b/python/MANIFEST.in deleted file mode 100644 index 46790eb..0000000 --- a/python/MANIFEST.in +++ /dev/null @@ -1,4 +0,0 @@ -include README.md -include LICENSE -recursive-include examples *.py -recursive-include tests *.py diff --git a/python/README.md b/python/README.md deleted file mode 100644 index fb5db36..0000000 --- a/python/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# Python Bindings for libbitcoinpqc - -This package provides Python bindings for the libbitcoinpqc library, which implements post-quantum cryptographic signature algorithms for use with BIP-360 and the Bitcoin QuBit soft fork. - -## Supported Algorithms - -- **ML-DSA-44** (CRYSTALS-Dilithium): A structured lattice-based digital signature scheme -- **SLH-DSA-Shake-128s** (SPHINCS+): A stateless hash-based signature scheme -- **FN-DSA-512** (FALCON): A lattice-based signature scheme designed for efficiency - -## Installation - -```bash -# Install the package -pip install bitcoinpqc -``` - -or from source: - -```bash -# Clone the repository -git clone https://github.com/bitcoin/libbitcoinpqc.git -cd libbitcoinpqc - -# Build the C library -mkdir build && cd build -cmake .. -make -cd .. - -# Install the Python package -cd python -pip install -e . -``` - -## Requirements - -- Python 3.7 or higher -- The libbitcoinpqc C library must be built and installed - -## Example Usage - -```python -import secrets -from bitcoinpqc import Algorithm, keygen, sign, verify - -# Generate random data for key generation -random_data = secrets.token_bytes(128) - -# Generate a key pair -algorithm = Algorithm.ML_DSA_44 # CRYSTALS-Dilithium -keypair = keygen(algorithm, random_data) - -# Create a message to sign -message = b"Hello, Bitcoin PQC!" - -# Sign the message -signature = sign(algorithm, keypair.secret_key, message) - -# Verify the signature -is_valid = verify(algorithm, keypair.public_key, message, signature) -print(f"Signature valid: {is_valid}") # Should print True -``` - -## Running Tests - -```bash -# Run the tests -./run_tests.sh - -# Or using unittest directly -python -m unittest discover -s tests -``` - -## License - -This project is licensed under the MIT License. diff --git a/python/bitcoinpqc/__init__.py b/python/bitcoinpqc/__init__.py deleted file mode 100644 index 04fcc06..0000000 --- a/python/bitcoinpqc/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -Bitcoin PQC Python API - -This package provides Python bindings for the libbitcoinpqc library, -which implements post-quantum cryptographic signature algorithms. -""" - -from .bitcoinpqc import ( - Algorithm, - Error, - KeyPair, - Signature, - public_key_size, - secret_key_size, - signature_size, - keygen, - sign, - verify -) - -__version__ = "0.1.0" diff --git a/python/bitcoinpqc/bitcoinpqc.py b/python/bitcoinpqc/bitcoinpqc.py deleted file mode 100644 index 7a720ce..0000000 --- a/python/bitcoinpqc/bitcoinpqc.py +++ /dev/null @@ -1,533 +0,0 @@ -""" -Bitcoin PQC Python Bindings - -This module provides Python bindings for the libbitcoinpqc C library. -""" - -import ctypes -import enum -import os -import platform -from pathlib import Path -from typing import Optional, Tuple, Union, List - - -# Find the library file -def _find_library(): - """Find the bitcoinpqc shared library.""" - # Try to find the library in common locations - search_paths = [ - # Current directory - Path.cwd(), - # Library's parent directory - Path(__file__).parent.parent.parent, - # Standard system paths - Path("/usr/lib"), - Path("/usr/local/lib"), - ] - - # Add build directories - # CMake build directory - search_paths.append(Path(__file__).parent.parent.parent / "build" / "lib") - # Rust build directories - search_paths.append(Path(__file__).parent.parent.parent / "target" / "debug") - search_paths.append(Path(__file__).parent.parent.parent / "target" / "debug" / "deps") - search_paths.append(Path(__file__).parent.parent.parent / "target" / "release") - search_paths.append(Path(__file__).parent.parent.parent / "target" / "release" / "deps") - - # Add paths from LD_LIBRARY_PATH environment variable - lib_path_env = None - if platform.system() == "Windows": - lib_path_env = os.environ.get("PATH", "") - elif platform.system() == "Darwin": - lib_path_env = os.environ.get("DYLD_LIBRARY_PATH", "") - else: # Linux/Unix - lib_path_env = os.environ.get("LD_LIBRARY_PATH", "") - - if lib_path_env: - for path in lib_path_env.split(os.pathsep): - if path: - search_paths.append(Path(path)) - - # Platform-specific library name - if platform.system() == "Windows": - lib_names = ["bitcoinpqc.dll"] - elif platform.system() == "Darwin": # macOS - lib_names = ["libbitcoinpqc.dylib", "libbitcoinpqc.so"] - else: # Linux/Unix - lib_names = ["libbitcoinpqc.so", "libbitcoinpqc.dylib"] - - # Don't try to load static libraries with ctypes - # lib_names.append("libbitcoinpqc.a") - - # Try each possible file path - found_paths = [] - for path in search_paths: - for name in lib_names: - lib_path = path / name - if lib_path.exists(): - found_paths.append(str(lib_path)) - - if found_paths: - return found_paths[0] # Return the first found library - - # If not found, let the OS loader find it - if platform.system() == "Windows": - return "bitcoinpqc" - else: - return "bitcoinpqc" - - -# Define enums to match C API -class Algorithm(enum.IntEnum): - """Algorithm types from bitcoin_pqc_algorithm_t.""" - SECP256K1_SCHNORR = 0 - FN_DSA_512 = 1 # FALCON-512 - ML_DSA_44 = 2 # CRYSTALS-Dilithium Level I - SLH_DSA_SHAKE_128S = 3 # SPHINCS+-128s - - -class Error(enum.IntEnum): - """Error codes from bitcoin_pqc_error_t.""" - OK = 0 - BAD_ARG = -1 - BAD_KEY = -2 - BAD_SIGNATURE = -3 - NOT_IMPLEMENTED = -4 - - -# Find and load the library -_lib_path = _find_library() -_MOCK_MODE = False # Flag to indicate if we're using mock mode - -try: - print(f"Attempting to load library from: {_lib_path}") - _lib = ctypes.CDLL(_lib_path) - - # Check if the library has the required functions - required_functions = [ - "bitcoin_pqc_public_key_size", - "bitcoin_pqc_secret_key_size", - "bitcoin_pqc_signature_size", - "bitcoin_pqc_keygen", - "bitcoin_pqc_keypair_free", - "bitcoin_pqc_sign", - "bitcoin_pqc_signature_free", - "bitcoin_pqc_verify" - ] - - missing_functions = [] - for func_name in required_functions: - if not hasattr(_lib, func_name): - missing_functions.append(func_name) - - if missing_functions: - print(f"Library found but missing required functions: {', '.join(missing_functions)}") - print("This appears to be the Rust library without the C API exposed.") - print("Using mock implementation instead.") - _MOCK_MODE = True - else: - print(f"Successfully loaded library with all required functions") -except (OSError, TypeError) as e: - # Try with just the basename as a last resort - try: - if platform.system() == "Windows": - _lib = ctypes.CDLL("bitcoinpqc") - else: - _lib = ctypes.CDLL("libbitcoinpqc") - print("Loaded library using system search paths") - except (OSError, TypeError) as e2: - print(f"Failed to load library from {_lib_path}: {e}") - print(f"Also failed with default name: {e2}") - - print("Using mock implementation for testing purposes") - _MOCK_MODE = True - -# If we're using mock mode, create a mock implementation -if _MOCK_MODE: - print("Creating mock implementation of the Bitcoin PQC library") - - # Create a mock function class that supports argtypes and restype - class MockFunction: - def __init__(self, func): - self.func = func - self.argtypes = None - self.restype = None - - def __call__(self, *args, **kwargs): - return self.func(*args, **kwargs) - - # Create mock class with all required functions - class MockLib: - def __init__(self): - # Create function attributes with MockFunction wrappers - self.bitcoin_pqc_public_key_size = MockFunction(self._bitcoin_pqc_public_key_size) - self.bitcoin_pqc_secret_key_size = MockFunction(self._bitcoin_pqc_secret_key_size) - self.bitcoin_pqc_signature_size = MockFunction(self._bitcoin_pqc_signature_size) - self.bitcoin_pqc_keygen = MockFunction(self._bitcoin_pqc_keygen) - self.bitcoin_pqc_keypair_free = MockFunction(self._bitcoin_pqc_keypair_free) - self.bitcoin_pqc_sign = MockFunction(self._bitcoin_pqc_sign) - self.bitcoin_pqc_signature_free = MockFunction(self._bitcoin_pqc_signature_free) - self.bitcoin_pqc_verify = MockFunction(self._bitcoin_pqc_verify) - - def _bitcoin_pqc_public_key_size(self, algorithm): - sizes = { - 0: 32, # SECP256K1_SCHNORR - 1: 897, # FN_DSA_512 - 2: 1312, # ML_DSA_44 - 3: 32, # SLH_DSA_SHAKE_128S - } - return sizes.get(algorithm, 32) - - def _bitcoin_pqc_secret_key_size(self, algorithm): - sizes = { - 0: 32, # SECP256K1_SCHNORR - 1: 1281, # FN_DSA_512 - 2: 2528, # ML_DSA_44 - 3: 64, # SLH_DSA_SHAKE_128S - } - return sizes.get(algorithm, 64) - - def _bitcoin_pqc_signature_size(self, algorithm): - sizes = { - 0: 64, # SECP256K1_SCHNORR - 1: 666, # FN_DSA_512 - 2: 2420, # ML_DSA_44 - 3: 7856, # SLH_DSA_SHAKE_128S - } - return sizes.get(algorithm, 64) - - def _bitcoin_pqc_keygen(self, algorithm, keypair_ptr, random_data, random_data_size): - # In the mock, we need to directly access the pointer - # Check if we're dealing with a pointer from byref or a direct pointer - try: - # Try to access the object this is pointing to - keypair = keypair_ptr._obj - except (AttributeError, TypeError): - try: - # Try the regular contents access - keypair = keypair_ptr.contents - except (AttributeError, TypeError): - # Last resort: assume it's already the object - keypair = keypair_ptr - - keypair.algorithm = algorithm - - # Allocate mock public key - pub_size = self._bitcoin_pqc_public_key_size(algorithm) - pub_key = (ctypes.c_uint8 * pub_size)() - for i in range(min(pub_size, len(random_data))): - pub_key[i] = random_data[i] - keypair.public_key = ctypes.cast(pub_key, ctypes.c_void_p) - keypair.public_key_size = pub_size - - # Allocate mock secret key - sec_size = self._bitcoin_pqc_secret_key_size(algorithm) - sec_key = (ctypes.c_uint8 * sec_size)() - for i in range(min(sec_size, len(random_data))): - sec_key[i] = random_data[i] - keypair.secret_key = ctypes.cast(sec_key, ctypes.c_void_p) - keypair.secret_key_size = sec_size - - return 0 # Success - - def _bitcoin_pqc_keypair_free(self, keypair_ptr): - # In a real implementation, we would free the memory - pass - - def _bitcoin_pqc_sign(self, algorithm, secret_key, secret_key_size, - message, message_size, signature_ptr): - # In the mock, we need to directly access the pointer - try: - # Try to access the object this is pointing to - signature = signature_ptr._obj - except (AttributeError, TypeError): - try: - # Try the regular contents access - signature = signature_ptr.contents - except (AttributeError, TypeError): - # Last resort: assume it's already the object - signature = signature_ptr - - signature.algorithm = algorithm - - # Allocate mock signature - sig_size = self._bitcoin_pqc_signature_size(algorithm) - sig_data = (ctypes.c_uint8 * sig_size)() - - # Create a deterministic "signature" based on the message - import hashlib - msg_bytes = bytes(message[:message_size]) - digest = hashlib.sha256(msg_bytes).digest() - for i in range(min(sig_size, len(digest))): - sig_data[i] = digest[i] - - signature.signature = ctypes.cast(sig_data, ctypes.POINTER(ctypes.c_uint8)) - signature.signature_size = sig_size - - return 0 # Success - - def _bitcoin_pqc_signature_free(self, signature_ptr): - # In a real implementation, we would free the memory - pass - - def _bitcoin_pqc_verify(self, algorithm, public_key, public_key_size, - message, message_size, signature, signature_size): - # Mock verification - in real life we'd verify the signature - # For mock purposes, we'll just validate sizes are correct - if public_key_size != self._bitcoin_pqc_public_key_size(algorithm): - return -2 # BAD_KEY - - if signature_size != self._bitcoin_pqc_signature_size(algorithm): - return -3 # BAD_SIGNATURE - - # Create deterministic verification result based on the message - # For testing, we'll verify the same message that was signed - import hashlib - - # Convert message to bytes - handle both buffer types and direct pointers - try: - # Try to get a slice directly - msg_bytes = bytes(message[:message_size]) - except (TypeError, AttributeError): - # If that fails, try to create a ctypes buffer and copy - try: - msg_buffer = (ctypes.c_uint8 * message_size)() - for i in range(message_size): - msg_buffer[i] = message[i] - msg_bytes = bytes(msg_buffer) - except: - # Last resort: assume it's already bytes - msg_bytes = message - - digest = hashlib.sha256(msg_bytes).digest() - - # Check first few bytes of signature match our mock signature generation - for i in range(min(16, signature_size, len(digest))): - if signature[i] != digest[i]: - return -3 # BAD_SIGNATURE - - return 0 # Success - - _lib = MockLib() - - -# Define C structures and function prototypes - -# KeyPair structure -class _CKeyPair(ctypes.Structure): - _fields_ = [ - ("algorithm", ctypes.c_int), - ("public_key", ctypes.c_void_p), - ("secret_key", ctypes.c_void_p), - ("public_key_size", ctypes.c_size_t), - ("secret_key_size", ctypes.c_size_t) - ] - - -# Signature structure -class _CSignature(ctypes.Structure): - _fields_ = [ - ("algorithm", ctypes.c_int), - ("signature", ctypes.POINTER(ctypes.c_uint8)), - ("signature_size", ctypes.c_size_t) - ] - - -# Define function prototypes -_lib.bitcoin_pqc_public_key_size.argtypes = [ctypes.c_int] -_lib.bitcoin_pqc_public_key_size.restype = ctypes.c_size_t - -_lib.bitcoin_pqc_secret_key_size.argtypes = [ctypes.c_int] -_lib.bitcoin_pqc_secret_key_size.restype = ctypes.c_size_t - -_lib.bitcoin_pqc_signature_size.argtypes = [ctypes.c_int] -_lib.bitcoin_pqc_signature_size.restype = ctypes.c_size_t - -_lib.bitcoin_pqc_keygen.argtypes = [ - ctypes.c_int, - ctypes.POINTER(_CKeyPair), - ctypes.POINTER(ctypes.c_uint8), - ctypes.c_size_t -] -_lib.bitcoin_pqc_keygen.restype = ctypes.c_int - -_lib.bitcoin_pqc_keypair_free.argtypes = [ctypes.POINTER(_CKeyPair)] -_lib.bitcoin_pqc_keypair_free.restype = None - -_lib.bitcoin_pqc_sign.argtypes = [ - ctypes.c_int, - ctypes.POINTER(ctypes.c_uint8), - ctypes.c_size_t, - ctypes.POINTER(ctypes.c_uint8), - ctypes.c_size_t, - ctypes.POINTER(_CSignature) -] -_lib.bitcoin_pqc_sign.restype = ctypes.c_int - -_lib.bitcoin_pqc_signature_free.argtypes = [ctypes.POINTER(_CSignature)] -_lib.bitcoin_pqc_signature_free.restype = None - -_lib.bitcoin_pqc_verify.argtypes = [ - ctypes.c_int, - ctypes.POINTER(ctypes.c_uint8), - ctypes.c_size_t, - ctypes.POINTER(ctypes.c_uint8), - ctypes.c_size_t, - ctypes.POINTER(ctypes.c_uint8), - ctypes.c_size_t -] -_lib.bitcoin_pqc_verify.restype = ctypes.c_int - - -# Python wrapper classes - -class KeyPair: - """Bitcoin PQC key pair wrapper.""" - - def __init__(self, algorithm: Algorithm, keypair: _CKeyPair): - """Initialize from a C keypair structure.""" - self.algorithm = algorithm - self._keypair = keypair - - # Extract public and secret keys - if keypair.public_key and keypair.public_key_size > 0: - public_key = (ctypes.c_uint8 * keypair.public_key_size)() - ctypes.memmove(public_key, keypair.public_key, keypair.public_key_size) - self.public_key = bytes(public_key) - else: - self.public_key = b'' - - if keypair.secret_key and keypair.secret_key_size > 0: - secret_key = (ctypes.c_uint8 * keypair.secret_key_size)() - ctypes.memmove(secret_key, keypair.secret_key, keypair.secret_key_size) - self.secret_key = bytes(secret_key) - else: - self.secret_key = b'' - - def __del__(self): - """Free C resources.""" - try: - if hasattr(self, '_keypair'): - _lib.bitcoin_pqc_keypair_free(ctypes.byref(self._keypair)) - del self._keypair - except (AttributeError, TypeError): - # Library might already be unloaded during interpreter shutdown - pass - - -class Signature: - """Bitcoin PQC signature wrapper.""" - - def __init__(self, algorithm: Algorithm, signature: Optional[_CSignature] = None, raw_signature: Optional[bytes] = None): - """Initialize from either a C signature structure or raw bytes.""" - self.algorithm = algorithm - self._signature = signature - - if signature: - # Extract signature bytes - if signature.signature and signature.signature_size > 0: - sig_buffer = (ctypes.c_uint8 * signature.signature_size)() - ctypes.memmove(sig_buffer, signature.signature, signature.signature_size) - self.signature = bytes(sig_buffer) - else: - self.signature = b'' - elif raw_signature: - self.signature = raw_signature - else: - raise ValueError("Must provide either signature or raw_signature") - - def __del__(self): - """Free C resources.""" - try: - if hasattr(self, '_signature') and self._signature: - _lib.bitcoin_pqc_signature_free(ctypes.byref(self._signature)) - del self._signature - except (AttributeError, TypeError): - # Library might already be unloaded during interpreter shutdown - pass - - -# API Functions - -def public_key_size(algorithm: Algorithm) -> int: - """Get the public key size for an algorithm.""" - return _lib.bitcoin_pqc_public_key_size(algorithm) - - -def secret_key_size(algorithm: Algorithm) -> int: - """Get the secret key size for an algorithm.""" - return _lib.bitcoin_pqc_secret_key_size(algorithm) - - -def signature_size(algorithm: Algorithm) -> int: - """Get the signature size for an algorithm.""" - return _lib.bitcoin_pqc_signature_size(algorithm) - - -def keygen(algorithm: Algorithm, random_data: bytes) -> KeyPair: - """Generate a key pair.""" - if len(random_data) < 128: - raise ValueError("Random data must be at least 128 bytes") - - random_buffer = (ctypes.c_uint8 * len(random_data)).from_buffer_copy(random_data) - keypair = _CKeyPair() - - result = _lib.bitcoin_pqc_keygen( - algorithm, - ctypes.byref(keypair), - random_buffer, - len(random_data) - ) - - if result != Error.OK: - raise Exception(f"Key generation failed with error code: {result}") - - return KeyPair(algorithm, keypair) - - -def sign(algorithm: Algorithm, secret_key: bytes, message: bytes) -> Signature: - """Sign a message.""" - secret_buffer = (ctypes.c_uint8 * len(secret_key)).from_buffer_copy(secret_key) - message_buffer = (ctypes.c_uint8 * len(message)).from_buffer_copy(message) - signature = _CSignature() - - result = _lib.bitcoin_pqc_sign( - algorithm, - secret_buffer, - len(secret_key), - message_buffer, - len(message), - ctypes.byref(signature) - ) - - if result != Error.OK: - raise Exception(f"Signing failed with error code: {result}") - - return Signature(algorithm, signature) - - -def verify(algorithm: Algorithm, public_key: bytes, message: bytes, signature: Union[Signature, bytes]) -> bool: - """Verify a signature.""" - public_buffer = (ctypes.c_uint8 * len(public_key)).from_buffer_copy(public_key) - message_buffer = (ctypes.c_uint8 * len(message)).from_buffer_copy(message) - - # Handle both Signature objects and raw signature bytes - if isinstance(signature, Signature): - sig_bytes = signature.signature - else: - sig_bytes = signature - - sig_buffer = (ctypes.c_uint8 * len(sig_bytes)).from_buffer_copy(sig_bytes) - - result = _lib.bitcoin_pqc_verify( - algorithm, - public_buffer, - len(public_key), - message_buffer, - len(message), - sig_buffer, - len(sig_bytes) - ) - - return result == Error.OK diff --git a/python/check_library.py b/python/check_library.py deleted file mode 100755 index f086e79..0000000 --- a/python/check_library.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python3 -""" -Check if the libbitcoinpqc C library can be found and loaded. -""" - -import os -import sys -import ctypes -from pathlib import Path -import platform -from datetime import datetime - - -def find_library(): - """Find the bitcoinpqc shared library.""" - search_paths = [ - Path.cwd(), - Path(__file__).parent.parent, - Path("/usr/lib"), - Path("/usr/local/lib"), - # CMake build directory - Path(__file__).parent.parent / "build" / "lib", - # Rust build directories - Path(__file__).parent.parent / "target" / "debug", - Path(__file__).parent.parent / "target" / "debug" / "deps", - Path(__file__).parent.parent / "target" / "release", - Path(__file__).parent.parent / "target" / "release" / "deps", - ] - - if platform.system() == "Windows": - lib_names = ["bitcoinpqc.dll"] - elif platform.system() == "Darwin": # macOS - lib_names = ["libbitcoinpqc.dylib", "libbitcoinpqc.so"] - else: # Linux/Unix - lib_names = ["libbitcoinpqc.so", "libbitcoinpqc.dylib"] - - print("Searching for library...") - for path in search_paths: - print(f"Looking in {path}") - for name in lib_names: - lib_path = path / name - if lib_path.exists(): - print(f"Found at: {lib_path}") - return str(lib_path) - - print("Library not found in standard locations") - return None - - -def main(): - """Check if the C library can be loaded.""" - print("Bitcoin PQC Library Check Utility") - print("=================================") - - # Check if we're running from the source directory - if Path(__file__).parent.name == "python": - print("Running from python source directory") - - # Find the library - lib_path = find_library() - - if lib_path is None: - print("Could not find the libbitcoinpqc library") - print("\nTry building the C library with:") - print(" mkdir -p build && cd build && cmake .. && make") - print(" cd ..") - sys.exit(1) - - # Try to load the library - try: - print(f"Attempting to load {lib_path}") - lib = ctypes.CDLL(lib_path) - print("Successfully loaded the library!") - - # Check if basic functions are available - if hasattr(lib, "bitcoin_pqc_public_key_size"): - print("Found bitcoin_pqc_public_key_size function") - else: - print("WARNING: bitcoin_pqc_public_key_size function not found") - - # Print the library info - print("\nLibrary Information:") - print(f" Path: {lib_path}") - print(f" Size: {os.path.getsize(lib_path) / 1024:.1f} KB") - print(f" Modified: {datetime.fromtimestamp(os.path.getmtime(lib_path)).strftime('%Y-%m-%d %H:%M:%S')}") - - print("\nAll checks passed. The Python bindings should work correctly.") - return 0 - except Exception as e: - print(f"Failed to load the library: {e}") - print("\nPossible solutions:") - print("1. Make sure you have built the C library correctly") - print("2. Check that the library file exists and is readable") - print("3. On Linux, add the library directory to LD_LIBRARY_PATH:") - print(" export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/library/dir") - print("4. On macOS, add the library directory to DYLD_LIBRARY_PATH:") - print(" export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/path/to/library/dir") - sys.exit(1) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/python/examples/__init__.py b/python/examples/__init__.py deleted file mode 100644 index 1182e62..0000000 --- a/python/examples/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Examples for libbitcoinpqc Python bindings.""" diff --git a/python/examples/basic_usage.py b/python/examples/basic_usage.py deleted file mode 100644 index f6ba1cf..0000000 --- a/python/examples/basic_usage.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python3 -""" -Basic usage example for the bitcoinpqc Python bindings. -""" - -import os -import sys -import secrets -from pathlib import Path -import time - -# Add the parent directory to the path so we can import the module -sys.path.insert(0, str(Path(__file__).parent.parent)) - -from bitcoinpqc import Algorithm, keygen, sign, verify - - -def main(): - """Run a basic example of bitcoinpqc usage.""" - # Choose an algorithm - algorithm = Algorithm.ML_DSA_44 # CRYSTALS-Dilithium - - # Generate random data for key generation - random_data = secrets.token_bytes(128) - - print(f"Generating key pair for {algorithm.name}...") - start = time.time() - keypair = keygen(algorithm, random_data) - keygen_time = time.time() - start - - print(f"Key generation took {keygen_time:.4f} seconds") - print(f"Public key size: {len(keypair.public_key)} bytes") - print(f"Secret key size: {len(keypair.secret_key)} bytes") - - # Sign a message - message = b"This is a test message for Bitcoin PQC signatures." - print(f"\nSigning message: {message.decode('utf-8')}") - - start = time.time() - signature = sign(algorithm, keypair.secret_key, message) - sign_time = time.time() - start - - print(f"Signing took {sign_time:.4f} seconds") - print(f"Signature size: {len(signature.signature)} bytes") - - # Verify the signature - print("\nVerifying signature...") - - start = time.time() - is_valid = verify(algorithm, keypair.public_key, message, signature) - verify_time = time.time() - start - - print(f"Verification took {verify_time:.4f} seconds") - print(f"Signature is valid: {is_valid}") - - # Verify with incorrect message - bad_message = b"This is NOT the original message!" - print("\nVerifying signature with incorrect message...") - - is_valid = verify(algorithm, keypair.public_key, bad_message, signature) - print(f"Signature is valid (should be False): {is_valid}") - - -if __name__ == "__main__": - main() diff --git a/python/run_tests.sh b/python/run_tests.sh deleted file mode 100755 index 47e2af8..0000000 --- a/python/run_tests.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -# Run the Python tests for libbitcoinpqc - -# Exit on any error -set -e - -echo "Running libbitcoinpqc Python API tests..." - -# Check if the library can be found -if [ -f "../build/lib/libbitcoinpqc.so" ] || [ -f "../build/lib/libbitcoinpqc.dylib" ]; then - echo "Found library at ../build/lib" -elif [ -f "../target/debug/libbitcoinpqc.so" ] || [ -f "../target/debug/libbitcoinpqc.dylib" ]; then - echo "Found Rust library at ../target/debug" - echo "Using mock implementation for testing" - export BITCOINPQC_ALLOW_MOCK=1 - - # Add this to LD_LIBRARY_PATH for the current session - # (Not needed with mock implementation, but kept for documentation) - # export LD_LIBRARY_PATH="../target/debug:$LD_LIBRARY_PATH" -elif [ -f "../target/release/libbitcoinpqc.so" ] || [ -f "../target/release/libbitcoinpqc.dylib" ]; then - echo "Found Rust library at ../target/release" - echo "Using mock implementation for testing" - export BITCOINPQC_ALLOW_MOCK=1 - - # Add this to LD_LIBRARY_PATH for the current session - # (Not needed with mock implementation, but kept for documentation) - # export LD_LIBRARY_PATH="../target/release:$LD_LIBRARY_PATH" -elif [ -f "/usr/lib/libbitcoinpqc.so" ] || [ -f "/usr/lib/libbitcoinpqc.dylib" ]; then - echo "Found library at /usr/lib" -elif [ -f "/usr/local/lib/libbitcoinpqc.so" ] || [ -f "/usr/local/lib/libbitcoinpqc.dylib" ]; then - echo "Found library at /usr/local/lib" -else - echo "WARNING: Library not found, using mock implementation for testing" - export BITCOINPQC_ALLOW_MOCK=1 -fi - -# Run unittest tests -python3 -m unittest discover -s tests - -echo "All tests passed!" - -# Run the example -echo -e "\nRunning example..." -python3 examples/basic_usage.py diff --git a/python/setup.py b/python/setup.py deleted file mode 100644 index 5fdd919..0000000 --- a/python/setup.py +++ /dev/null @@ -1,38 +0,0 @@ -from setuptools import setup, find_packages -import os - -# Get the absolute path to the directory containing setup.py -here = os.path.abspath(os.path.dirname(__file__)) - -# Read the README.md file safely -with open(os.path.join(here, "README.md"), encoding="utf-8") as f: - long_description = f.read() - -# Use the README.md in the python directory if it exists, otherwise use the root README -if not os.path.exists(os.path.join(here, "README.md")): - with open(os.path.join(here, "..", "README.md"), encoding="utf-8") as f: - long_description = f.read() - -setup( - name="bitcoinpqc", - version="0.1.0", - packages=find_packages(), - description="Python bindings for libbitcoinpqc", - long_description=long_description, - long_description_content_type="text/markdown", - author="Bitcoin PQC Developers", - url="https://github.com/bitcoinpqc/libbitcoinpqc", - classifiers=[ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - ], - python_requires=">=3.7", - # Add explicit entry for test_suite if you have tests - test_suite="tests", -) diff --git a/python/tests/__init__.py b/python/tests/__init__.py deleted file mode 100644 index e679cdf..0000000 --- a/python/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Test package for libbitcoinpqc Python bindings.""" diff --git a/python/tests/test_bitcoinpqc.py b/python/tests/test_bitcoinpqc.py deleted file mode 100644 index a209d32..0000000 --- a/python/tests/test_bitcoinpqc.py +++ /dev/null @@ -1,77 +0,0 @@ -import unittest -import os -import sys -import secrets -from pathlib import Path - -# Add the parent directory to the path so we can import the module -sys.path.insert(0, str(Path(__file__).parent.parent)) - -import bitcoinpqc -from bitcoinpqc import Algorithm - - -class TestBitcoinPQC(unittest.TestCase): - - def test_key_sizes(self): - """Test key size reporting functions.""" - for algo in [ - Algorithm.FN_DSA_512, - Algorithm.ML_DSA_44, - Algorithm.SLH_DSA_SHAKE_128S - ]: - # Verify sizes are non-zero - self.assertGreater(bitcoinpqc.public_key_size(algo), 0) - self.assertGreater(bitcoinpqc.secret_key_size(algo), 0) - self.assertGreater(bitcoinpqc.signature_size(algo), 0) - - def _test_algorithm(self, algorithm): - """Test key generation, signing, and verification for a specific algorithm.""" - # Generate random data for key generation - random_data = secrets.token_bytes(128) - - # Generate a keypair - keypair = bitcoinpqc.keygen(algorithm, random_data) - - # Verify key sizes match reported sizes - self.assertEqual(len(keypair.public_key), bitcoinpqc.public_key_size(algorithm)) - self.assertEqual(len(keypair.secret_key), bitcoinpqc.secret_key_size(algorithm)) - - # Test message signing - message = b"Hello, Bitcoin PQC!" - signature = bitcoinpqc.sign(algorithm, keypair.secret_key, message) - - # Verify signature size matches reported size - self.assertEqual(len(signature.signature), bitcoinpqc.signature_size(algorithm)) - - # Verify the signature - self.assertTrue(bitcoinpqc.verify( - algorithm, keypair.public_key, message, signature - )) - - # Verify with raw signature bytes - self.assertTrue(bitcoinpqc.verify( - algorithm, keypair.public_key, message, signature.signature - )) - - # Verify that the signature doesn't verify for a different message - bad_message = b"Bad message!" - self.assertFalse(bitcoinpqc.verify( - algorithm, keypair.public_key, bad_message, signature - )) - - def test_fn_dsa(self): - """Test FN-DSA-512 (FALCON) algorithm.""" - self._test_algorithm(Algorithm.FN_DSA_512) - - def test_ml_dsa(self): - """Test ML-DSA-44 (Dilithium) algorithm.""" - self._test_algorithm(Algorithm.ML_DSA_44) - - def test_slh_dsa(self): - """Test SLH-DSA-SHAKE-128s (SPHINCS+) algorithm.""" - self._test_algorithm(Algorithm.SLH_DSA_SHAKE_128S) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/bindings_include.rs b/src/bindings_include.rs deleted file mode 100644 index f3a33ab..0000000 --- a/src/bindings_include.rs +++ /dev/null @@ -1,207 +0,0 @@ -// This file exists to solve the problem with OUT_DIR not being -// available in the IDE but required for builds. -// The build script always generates bindings.rs in the OUT_DIR. - -// When compiling for real, include the real bindings -#[cfg(all(not(feature = "ide"), not(doc)))] -include!(concat!(env!("OUT_DIR"), "/bindings.rs")); - -// For documentation, we need stubs to make doctests work -#[cfg(doc)] -pub mod doc_bindings { - // Define the essential types needed for documentation - #[repr(C)] - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub struct bitcoin_pqc_algorithm_t(pub u32); - - impl bitcoin_pqc_algorithm_t { - pub const BITCOIN_PQC_SECP256K1_SCHNORR: bitcoin_pqc_algorithm_t = - bitcoin_pqc_algorithm_t(0); - 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(2); - } - - #[repr(C)] - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub struct bitcoin_pqc_error_t(pub i32); - - impl bitcoin_pqc_error_t { - pub const BITCOIN_PQC_OK: bitcoin_pqc_error_t = bitcoin_pqc_error_t(0); - pub const BITCOIN_PQC_ERROR_BAD_ARG: bitcoin_pqc_error_t = bitcoin_pqc_error_t(-1); - pub const BITCOIN_PQC_ERROR_BAD_KEY: bitcoin_pqc_error_t = bitcoin_pqc_error_t(-2); - pub const BITCOIN_PQC_ERROR_BAD_SIGNATURE: bitcoin_pqc_error_t = bitcoin_pqc_error_t(-3); - pub const BITCOIN_PQC_ERROR_NOT_IMPLEMENTED: bitcoin_pqc_error_t = bitcoin_pqc_error_t(-4); - } - - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct bitcoin_pqc_keypair_t { - pub algorithm: bitcoin_pqc_algorithm_t, - pub public_key: *mut ::std::os::raw::c_uchar, - pub secret_key: *mut ::std::os::raw::c_uchar, - pub public_key_size: usize, - pub secret_key_size: usize, - } - - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct bitcoin_pqc_signature_t { - pub algorithm: bitcoin_pqc_algorithm_t, - pub signature: *mut ::std::os::raw::c_uchar, - pub signature_size: usize, - } - - // Dummy function declarations - pub unsafe fn bitcoin_pqc_keygen( - _algorithm: bitcoin_pqc_algorithm_t, - _keypair: *mut bitcoin_pqc_keypair_t, - _random_data: *const ::std::os::raw::c_uchar, - _random_data_len: usize, - ) -> bitcoin_pqc_error_t { - unimplemented!("This is a doc stub") - } - - pub unsafe fn bitcoin_pqc_keypair_free(_keypair: *mut bitcoin_pqc_keypair_t) {} - - #[allow(clippy::too_many_arguments)] - pub unsafe fn bitcoin_pqc_sign( - _algorithm: bitcoin_pqc_algorithm_t, - _secret_key: *const ::std::os::raw::c_uchar, - _secret_key_len: usize, - _message: *const ::std::os::raw::c_uchar, - _message_len: usize, - _signature: *mut bitcoin_pqc_signature_t, - ) -> bitcoin_pqc_error_t { - unimplemented!("This is a doc stub") - } - - pub unsafe fn bitcoin_pqc_verify( - _algorithm: bitcoin_pqc_algorithm_t, - _public_key: *const ::std::os::raw::c_uchar, - _public_key_len: usize, - _message: *const ::std::os::raw::c_uchar, - _message_len: usize, - _signature: *const ::std::os::raw::c_uchar, - _signature_len: usize, - ) -> bitcoin_pqc_error_t { - unimplemented!("This is a doc stub") - } - - pub unsafe fn bitcoin_pqc_signature_free(_signature: *mut bitcoin_pqc_signature_t) {} - - pub unsafe fn bitcoin_pqc_public_key_size(_algorithm: bitcoin_pqc_algorithm_t) -> usize { - 0 - } - - pub unsafe fn bitcoin_pqc_secret_key_size(_algorithm: bitcoin_pqc_algorithm_t) -> usize { - 0 - } - - pub unsafe fn bitcoin_pqc_signature_size(_algorithm: bitcoin_pqc_algorithm_t) -> usize { - 0 - } -} - -// For IDE support - similar stubs but are never compiled for release -#[cfg(feature = "ide")] -pub mod ide_bindings { - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct bitcoin_pqc_keypair_t { - pub algorithm: bitcoin_pqc_algorithm_t, - pub public_key: *mut ::std::os::raw::c_uchar, - pub secret_key: *mut ::std::os::raw::c_uchar, - pub public_key_size: usize, - pub secret_key_size: usize, - } - - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct bitcoin_pqc_signature_t { - pub algorithm: bitcoin_pqc_algorithm_t, - pub signature: *mut ::std::os::raw::c_uchar, - pub signature_size: usize, - } - - #[repr(C)] - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub struct bitcoin_pqc_algorithm_t(pub u32); - - impl bitcoin_pqc_algorithm_t { - pub const BITCOIN_PQC_SECP256K1_SCHNORR: bitcoin_pqc_algorithm_t = - bitcoin_pqc_algorithm_t(0); - 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(2); - } - - #[repr(C)] - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub struct bitcoin_pqc_error_t(pub i32); - - impl bitcoin_pqc_error_t { - pub const BITCOIN_PQC_OK: bitcoin_pqc_error_t = bitcoin_pqc_error_t(0); - pub const BITCOIN_PQC_ERROR_BAD_ARG: bitcoin_pqc_error_t = bitcoin_pqc_error_t(-1); - pub const BITCOIN_PQC_ERROR_BAD_KEY: bitcoin_pqc_error_t = bitcoin_pqc_error_t(-2); - pub const BITCOIN_PQC_ERROR_BAD_SIGNATURE: bitcoin_pqc_error_t = bitcoin_pqc_error_t(-3); - pub const BITCOIN_PQC_ERROR_NOT_IMPLEMENTED: bitcoin_pqc_error_t = bitcoin_pqc_error_t(-4); - } - - // Function declarations for IDE support - pub unsafe fn bitcoin_pqc_keygen( - _algorithm: bitcoin_pqc_algorithm_t, - _keypair: *mut bitcoin_pqc_keypair_t, - _random_data: *const ::std::os::raw::c_uchar, - _random_data_len: usize, - ) -> bitcoin_pqc_error_t { - unimplemented!("This is an IDE stub") - } - - pub unsafe fn bitcoin_pqc_keypair_free(_keypair: *mut bitcoin_pqc_keypair_t) {} - - #[allow(clippy::too_many_arguments)] - pub unsafe fn bitcoin_pqc_sign( - _algorithm: bitcoin_pqc_algorithm_t, - _secret_key: *const ::std::os::raw::c_uchar, - _secret_key_len: usize, - _message: *const ::std::os::raw::c_uchar, - _message_len: usize, - _signature: *mut bitcoin_pqc_signature_t, - ) -> bitcoin_pqc_error_t { - unimplemented!("This is an IDE stub") - } - - pub unsafe fn bitcoin_pqc_verify( - _algorithm: bitcoin_pqc_algorithm_t, - _public_key: *const ::std::os::raw::c_uchar, - _public_key_len: usize, - _message: *const ::std::os::raw::c_uchar, - _message_len: usize, - _signature: *const ::std::os::raw::c_uchar, - _signature_len: usize, - ) -> bitcoin_pqc_error_t { - unimplemented!("This is an IDE stub") - } - - pub unsafe fn bitcoin_pqc_signature_free(_signature: *mut bitcoin_pqc_signature_t) {} - - pub unsafe fn bitcoin_pqc_public_key_size(_algorithm: bitcoin_pqc_algorithm_t) -> usize { - 0 - } - - pub unsafe fn bitcoin_pqc_secret_key_size(_algorithm: bitcoin_pqc_algorithm_t) -> usize { - 0 - } - - pub unsafe fn bitcoin_pqc_signature_size(_algorithm: bitcoin_pqc_algorithm_t) -> usize { - 0 - } -} - -// Re-export the right set of bindings based on configuration -#[cfg(doc)] -pub use doc_bindings::*; - -#[cfg(feature = "ide")] -pub use ide_bindings::*; diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 7e8e978..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,698 +0,0 @@ -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] - -#[cfg(feature = "serde")] -use std::convert::TryFrom; -use std::error::Error as StdError; -use std::fmt; -use std::hash::Hash; -use std::ptr; - -use bitmask_enum::bitmask; -use secp256k1::{ - schnorr, All, Keypair as SecpKeypair, Secp256k1, SecretKey as SecpSecretKey, XOnlyPublicKey, -}; - -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; - -#[cfg(feature = "serde")] -mod hex_bytes { - use serde::{de::Error, Deserialize, Deserializer, Serializer}; - use std::vec::Vec; // Ensure Vec is in scope - - pub fn serialize(bytes: &Vec, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&hex::encode(bytes)) - } - - pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - hex::decode(s).map_err(Error::custom) - } -} - -// Include the auto-generated bindings using our wrapper -// Make it pub(crate) so doctests can access these symbols -pub(crate) mod bindings_include; -// Use a glob import to get all the symbols consistently -use bindings_include::*; - -/// Error type for PQC operations -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] -pub enum PqcError { - /// Invalid arguments provided - BadArgument, - /// Not enough data provided (e.g., for key generation) - InsufficientData, - /// Invalid key provided or invalid format for the specified algorithm - BadKey, - /// Invalid signature provided or invalid format for the specified algorithm - BadSignature, - /// Algorithm not implemented (e.g., trying to sign/keygen Secp256k1) - NotImplemented, - /// Provided public key and signature algorithms do not match - AlgorithmMismatch, - /// Secp256k1 context error (should be rare with global context) - Secp256k1Error(secp256k1::Error), - /// Other unexpected error from the C library - Other(i32), -} - -impl fmt::Display for PqcError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - PqcError::BadArgument => write!(f, "Invalid arguments provided"), - PqcError::InsufficientData => write!(f, "Not enough data provided"), - PqcError::BadKey => write!(f, "Invalid key provided or invalid format"), - PqcError::BadSignature => write!(f, "Invalid signature provided or invalid format"), - PqcError::NotImplemented => write!(f, "Algorithm not implemented"), - PqcError::AlgorithmMismatch => { - write!(f, "Public key and signature algorithms mismatch") - } - PqcError::Secp256k1Error(e) => write!(f, "Secp256k1 error: {e}"), - PqcError::Other(code) => write!(f, "Unexpected error code: {code}"), - } - } -} - -impl StdError for PqcError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - PqcError::Secp256k1Error(e) => Some(e), - _ => None, - } - } -} - -impl From for PqcError { - fn from(e: secp256k1::Error) -> Self { - PqcError::Secp256k1Error(e) - } -} - -impl From for Result<(), PqcError> { - fn from(error: bitcoin_pqc_error_t) -> Self { - match error { - bitcoin_pqc_error_t::BITCOIN_PQC_OK => Ok(()), - bitcoin_pqc_error_t::BITCOIN_PQC_ERROR_BAD_ARG => Err(PqcError::BadArgument), - bitcoin_pqc_error_t::BITCOIN_PQC_ERROR_BAD_KEY => Err(PqcError::BadKey), - bitcoin_pqc_error_t::BITCOIN_PQC_ERROR_BAD_SIGNATURE => Err(PqcError::BadSignature), - bitcoin_pqc_error_t::BITCOIN_PQC_ERROR_NOT_IMPLEMENTED => Err(PqcError::NotImplemented), - _ => Err(PqcError::Other(error.0)), - } - } -} - -/// PQC Algorithm type -#[bitmask(u8)] -// We derive serde conditionally, other traits like Debug, Clone, Eq, Hash etc. -// should be provided by the included C bindings or the bitmask macro. -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(try_from = "String", into = "String") -)] -pub enum Algorithm { - /// BIP-340 Schnorr + X-Only - Elliptic Curve Digital Signature Algorithm - SECP256K1_SCHNORR, - /// ML-DSA-44 (CRYSTALS-Dilithium) - Lattice-based signature scheme - ML_DSA_44, - /// SLH-DSA-Shake-128s (SPHINCS+) - Hash-based signature scheme - SLH_DSA_128S, -} - -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::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"), - } - } -} - -// Serde implementations using string representation directly on Algorithm -#[cfg(feature = "serde")] -impl TryFrom for Algorithm { - type Error = String; // Serde requires specific error handling - - fn try_from(s: String) -> Result { - match s.as_str() { - "SECP256K1_SCHNORR" => Ok(Algorithm::SECP256K1_SCHNORR), - "ML_DSA_44" => Ok(Algorithm::ML_DSA_44), - "SLH_DSA_128S" => Ok(Algorithm::SLH_DSA_128S), - _ => Err(format!("Unknown algorithm string: {s}")), - } - } -} - -#[cfg(feature = "serde")] -impl From for String { - fn from(alg: Algorithm) -> Self { - match alg { - Algorithm::SECP256K1_SCHNORR => "SECP256K1_SCHNORR".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 - } - } -} - -impl fmt::Display for Algorithm { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - Algorithm::SECP256K1_SCHNORR => write!(f, "SECP256K1_SCHNORR"), - Algorithm::ML_DSA_44 => write!(f, "ML_DSA_44"), - Algorithm::SLH_DSA_128S => write!(f, "SLH_DSA_128S"), - _ => write!(f, "Unknown({:b})", self.bits), - } - } -} - -impl Algorithm { - /// Returns a user-friendly debug string with the algorithm name - pub fn debug_name(&self) -> String { - match *self { - Algorithm::SECP256K1_SCHNORR => "SECP256K1_SCHNORR".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), - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct PublicKey { - /// The algorithm this key belongs to - #[cfg_attr(feature = "serde", serde(flatten))] - pub algorithm: Algorithm, - /// The raw key bytes (serialized as hex) - #[cfg_attr(feature = "serde", serde(with = "hex_bytes"))] - pub bytes: Vec, -} - -impl PublicKey { - /// Creates a PublicKey from an algorithm and a byte slice. - /// - /// Validates the length of the byte slice against the expected size for the algorithm. - /// For Secp256k1, also validates the byte format. - pub fn try_from_slice(algorithm: Algorithm, bytes: &[u8]) -> Result { - let expected_len = public_key_size(algorithm); - if bytes.len() != expected_len { - return Err(PqcError::BadKey); // Use BadKey for length mismatch - } - - // Additional validation for Secp256k1 keys - if algorithm == Algorithm::SECP256K1_SCHNORR { - XOnlyPublicKey::from_slice(bytes).map_err(|_| PqcError::BadKey)?; - } - - Ok(PublicKey { - algorithm, - bytes: bytes.to_vec(), - }) - } - - /// Creates a PublicKey from an algorithm and a hex string. - pub fn from_str(algorithm: Algorithm, s: &str) -> Result { - let bytes = hex::decode(s).map_err(|_| PqcError::BadArgument)?; - Self::try_from_slice(algorithm, &bytes) - } - - /// Returns the underlying secp256k1 XOnlyPublicKey if applicable. - pub fn secp256k1_key(&self) -> Result { - if self.algorithm == Algorithm::SECP256K1_SCHNORR { - XOnlyPublicKey::from_slice(&self.bytes).map_err(|_| PqcError::BadKey) - // Should be valid if constructed correctly - } else { - Err(PqcError::AlgorithmMismatch) - } - } -} - -/// Secret key wrapper -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct SecretKey { - /// The algorithm this key belongs to - #[cfg_attr(feature = "serde", serde(flatten))] - pub algorithm: Algorithm, - /// The raw key bytes (serialized as hex) - #[cfg_attr(feature = "serde", serde(with = "hex_bytes"))] - pub bytes: Vec, -} - -impl SecretKey { - /// Creates a SecretKey from an algorithm and a hex string. - pub fn from_str(algorithm: Algorithm, s: &str) -> Result { - let bytes = hex::decode(s).map_err(|_| PqcError::BadArgument)?; - Self::try_from_slice(algorithm, &bytes) - } - - /// Creates a SecretKey from an algorithm and a byte slice. - /// - /// Validates the length of the byte slice against the expected size for the algorithm. - /// For Secp256k1, also validates the byte format. - pub fn try_from_slice(algorithm: Algorithm, bytes: &[u8]) -> Result { - let expected_len = secret_key_size(algorithm); - if bytes.len() != expected_len { - return Err(PqcError::BadKey); - } - - // Additional validation for Secp256k1 keys - if algorithm == Algorithm::SECP256K1_SCHNORR { - // SecpSecretKey::from_slice does verification, checking if the key is valid (non-zero) - SecpSecretKey::from_slice(bytes).map_err(|_| PqcError::BadKey)?; - } - - Ok(SecretKey { - algorithm, - bytes: bytes.to_vec(), - }) - } - - /// Returns the underlying secp256k1 SecretKey if applicable. - pub fn secp256k1_key(&self) -> Result { - if self.algorithm == Algorithm::SECP256K1_SCHNORR { - SecpSecretKey::from_slice(&self.bytes).map_err(|_| PqcError::BadKey) - // Should be valid if constructed correctly - } else { - Err(PqcError::AlgorithmMismatch) - } - } -} - -impl Drop for SecretKey { - fn drop(&mut self) { - // Zero out secret key memory on drop - // Consider using crates like `zeroize` for more robust clearing - for byte in &mut self.bytes { - *byte = 0; - } - } -} - -/// Represents a signature (PQC or Secp256k1) -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct Signature { - /// The algorithm this signature belongs to - #[cfg_attr(feature = "serde", serde(flatten))] - pub algorithm: Algorithm, - /// The raw signature bytes (serialized as hex) - #[cfg_attr(feature = "serde", serde(with = "hex_bytes"))] - pub bytes: Vec, -} - -impl Signature { - /// Creates a Signature from an algorithm and a byte slice. - /// - /// Validates the length of the byte slice against the expected size for the algorithm. - /// For Secp256k1, also validates the byte format. - pub fn try_from_slice(algorithm: Algorithm, bytes: &[u8]) -> Result { - let expected_len = signature_size(algorithm); - if bytes.len() != expected_len { - return Err(PqcError::BadSignature); - } - - // Additional validation for Secp256k1 signatures - if algorithm == Algorithm::SECP256K1_SCHNORR { - // Schnorr signatures don't have a cheap validity check like keys, - // but from_slice checks the length (already done above). - schnorr::Signature::from_slice(bytes).map_err(|_| PqcError::BadSignature)?; - } - - Ok(Signature { - algorithm, - bytes: bytes.to_vec(), - }) - } - - /// Creates a Signature from an algorithm and a hex string. - pub fn from_str(algorithm: Algorithm, s: &str) -> Result { - let bytes = hex::decode(s).map_err(|_| PqcError::BadArgument)?; - Self::try_from_slice(algorithm, &bytes) - } - - /// Returns the underlying secp256k1 Schnorr Signature if applicable. - pub fn secp256k1_signature(&self) -> Result { - if self.algorithm == Algorithm::SECP256K1_SCHNORR { - schnorr::Signature::from_slice(&self.bytes).map_err(|_| PqcError::BadSignature) - // Should be valid if constructed correctly - } else { - Err(PqcError::AlgorithmMismatch) - } - } -} - -/// Key pair containing both public and secret keys -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct KeyPair { - /// The public key - pub public_key: PublicKey, - /// The secret key - pub secret_key: SecretKey, -} - -/// Generate a key pair for the specified algorithm using provided seed data. -/// -/// # Arguments -/// -/// * `algorithm` - The algorithm to use (PQC or Secp256k1) -/// * `random_data` - Seed bytes for key generation. -/// - For PQC algorithms, must be at least 128 bytes. -/// - For `SECP256K1_SCHNORR`, must be exactly 32 bytes representing the desired secret key. -/// -/// # Returns -/// -/// A new key pair on success, or an error if the `random_data` is invalid for the algorithm. -/// -pub fn generate_keypair(algorithm: Algorithm, random_data: &[u8]) -> Result { - if algorithm == Algorithm::SECP256K1_SCHNORR { - // For Secp256k1, random_data *is* the secret key. - let required_size = secret_key_size(algorithm); // Should be 32 - - // Check for insufficient data - if random_data.len() < required_size { - return Err(PqcError::InsufficientData); - } - - // Use the first 32 bytes, truncating excess data if provided - let key_data = &random_data[..required_size]; - - let secp = Secp256k1::::new(); // Context needed for key derivation - - // Attempt to create secret key from the provided data - let sk_result = SecpSecretKey::from_slice(key_data); - let sk = sk_result.map_err(|_| PqcError::BadKey)?; - - // Create KeyPair from secret key - let keypair = SecpKeypair::from_secret_key(&secp, &sk); - - // Derive the public key using from_keypair - let (pk, _parity) = XOnlyPublicKey::from_keypair(&keypair); // Destructure the tuple - - // Construct the structs - let public_key = PublicKey { - algorithm: Algorithm::SECP256K1_SCHNORR, - bytes: pk.serialize().to_vec(), // Serialize the XOnlyPublicKey part - }; - let secret_key = SecretKey { - algorithm: Algorithm::SECP256K1_SCHNORR, - bytes: sk.as_ref().to_vec(), // Use as_ref() to get &[u8] slice - }; - Ok(KeyPair { - public_key, - secret_key, - }) - } else { - // PQC key generation requires specific random data length - if random_data.len() < 128 { - return Err(PqcError::InsufficientData); - } - - unsafe { - let mut keypair = bitcoin_pqc_keypair_t { - algorithm: algorithm.into(), - public_key: ptr::null_mut(), - secret_key: ptr::null_mut(), - public_key_size: 0, - secret_key_size: 0, - }; - - let result = bitcoin_pqc_keygen( - algorithm.into(), - &mut keypair, - random_data.as_ptr(), - random_data.len(), - ); - - if result != bitcoin_pqc_error_t::BITCOIN_PQC_OK { - // Free potentially allocated (but invalid) memory on error - bitcoin_pqc_keypair_free(&mut keypair); - return Err(match result { - bitcoin_pqc_error_t::BITCOIN_PQC_ERROR_BAD_ARG => PqcError::BadArgument, - bitcoin_pqc_error_t::BITCOIN_PQC_ERROR_BAD_KEY => PqcError::BadKey, - bitcoin_pqc_error_t::BITCOIN_PQC_ERROR_NOT_IMPLEMENTED => { - PqcError::NotImplemented - } - _ => PqcError::Other(result.0 as i32), - }); - } - - // Extract and copy the keys - let pk_slice = std::slice::from_raw_parts( - keypair.public_key as *const u8, - keypair.public_key_size, - ); - let sk_slice = std::slice::from_raw_parts( - keypair.secret_key as *const u8, - keypair.secret_key_size, - ); - - let pk_bytes = pk_slice.to_vec(); - let sk_bytes = sk_slice.to_vec(); - - // Free the C memory - bitcoin_pqc_keypair_free(&mut keypair); - - // Construct the structs (validation is implicitly done by FFI success) - let public_key = PublicKey { - algorithm, - bytes: pk_bytes, - }; - let secret_key = SecretKey { - algorithm, - bytes: sk_bytes, - }; - - Ok(KeyPair { - public_key, - secret_key, - }) - } - } -} - -/// Sign a message using the specified secret key -/// -/// # Arguments -/// -/// * `secret_key` - The secret key to sign with -/// * `message` - The message to sign. -/// - For PQC algorithms, this is the raw message. -/// - For `SECP256K1_SCHNORR`, this *must* be a 32-byte hash of the message. -/// -/// # Returns -/// -/// A signature on success, or an error -pub fn sign(secret_key: &SecretKey, message: &[u8]) -> Result { - match secret_key.algorithm { - Algorithm::SECP256K1_SCHNORR => { - // For Secp256k1, message must be a 32-byte hash - let required_size = 32; - - // Check if message is too short - if message.len() < required_size { - return Err(PqcError::InsufficientData); - } - - // Use only the first 32 bytes if message is longer - let msg_data = &message[..required_size]; - - let secp = Secp256k1::::new(); // Signing context - - // Parse secret key - let sk = secret_key.secp256k1_key()?; - - // Create Keypair - let keypair = SecpKeypair::from_secret_key(&secp, &sk); - - // Sign using sign_schnorr_no_aux_rand with the (potentially truncated) message slice - let schnorr_sig = secp.sign_schnorr_no_aux_rand(msg_data, &keypair); - - // Construct result Signature - Ok(Signature { - algorithm: Algorithm::SECP256K1_SCHNORR, - bytes: schnorr_sig.as_ref().to_vec(), - }) - } - pqc_alg => { - // PQC Signing logic using FFI - unsafe { - let mut signature = bitcoin_pqc_signature_t { - algorithm: pqc_alg.into(), - signature: ptr::null_mut(), - signature_size: 0, - }; - - let result = bitcoin_pqc_sign( - pqc_alg.into(), - secret_key.bytes.as_ptr(), - secret_key.bytes.len(), - message.as_ptr(), - message.len(), - &mut signature, - ); - - if result != bitcoin_pqc_error_t::BITCOIN_PQC_OK { - return Err(match result { - bitcoin_pqc_error_t::BITCOIN_PQC_ERROR_BAD_ARG => PqcError::BadArgument, - bitcoin_pqc_error_t::BITCOIN_PQC_ERROR_BAD_KEY => PqcError::BadKey, - bitcoin_pqc_error_t::BITCOIN_PQC_ERROR_BAD_SIGNATURE => { - PqcError::BadSignature - } - bitcoin_pqc_error_t::BITCOIN_PQC_ERROR_NOT_IMPLEMENTED => { - PqcError::NotImplemented - } - _ => PqcError::Other(result.0 as i32), - }); - } - - let sig_slice = std::slice::from_raw_parts( - signature.signature as *const u8, - signature.signature_size, - ); - let sig_bytes = sig_slice.to_vec(); - - bitcoin_pqc_signature_free(&mut signature); - - Ok(Signature { - algorithm: pqc_alg, - bytes: sig_bytes, - }) - } - } - } -} - -/// Verify a signature using the specified public key -/// -/// # Arguments -/// -/// * `public_key` - The public key to verify with -/// * `message` - The message that was signed (assumed to be pre-hashed for Secp256k1) -/// * `signature` - The signature to verify -/// -/// # Returns -/// -/// Ok(()) if the signature is valid, an error otherwise -pub fn verify( - public_key: &PublicKey, - message: &[u8], - signature: &Signature, -) -> Result<(), PqcError> { - // Ensure the key and signature algorithms match - if public_key.algorithm != signature.algorithm { - return Err(PqcError::AlgorithmMismatch); - } - - match public_key.algorithm { - Algorithm::SECP256K1_SCHNORR => { - // For Secp256k1, message must be a 32-byte hash - let required_size = 32; - - // Check if message is too short - if message.len() < required_size { - return Err(PqcError::InsufficientData); - } - - // Use only the first 32 bytes if message is longer - let msg_data = &message[..required_size]; - - // Use secp256k1 library for verification - let secp = Secp256k1::::verification_only(); - let pk = public_key.secp256k1_key()?; - let sig = signature.secp256k1_signature()?; - - // Verify using verify_schnorr with the (potentially truncated) message slice - secp.verify_schnorr(&sig, msg_data, &pk) - .map_err(PqcError::Secp256k1Error) - } - pqc_alg => { - // Length check for public key (still useful) - if public_key.bytes.len() != public_key_size(pqc_alg) { - return Err(PqcError::BadKey); - } - - // NOTE: We do NOT check the signature length here against signature_size(pqc_alg) - // because some algorithms like FN-DSA have variable signature lengths. - // The C library's verify function should handle invalid lengths internally. - - // PQC Verification logic using FFI - unsafe { - let result = bitcoin_pqc_verify( - pqc_alg.into(), - public_key.bytes.as_ptr(), - public_key.bytes.len(), - message.as_ptr(), - message.len(), - signature.bytes.as_ptr(), - signature.bytes.len(), - ); - result.into() // Converts C error enum to Result<(), PqcError> - } - } - } -} - -/// Get the public key size for an algorithm -/// -/// # Arguments -/// -/// * `algorithm` - The algorithm to get the size for -/// -/// # Returns -/// -/// The size in bytes -pub fn public_key_size(algorithm: Algorithm) -> usize { - if algorithm == Algorithm::SECP256K1_SCHNORR { - 32 // XOnlyPublicKey size - } else { - unsafe { bitcoin_pqc_public_key_size(algorithm.into()) } - } -} - -/// Get the secret key size for an algorithm -/// -/// # Arguments -/// -/// * `algorithm` - The algorithm to get the size for -/// -/// # Returns -/// -/// The size in bytes -pub fn secret_key_size(algorithm: Algorithm) -> usize { - if algorithm == Algorithm::SECP256K1_SCHNORR { - 32 // secp256k1::SecretKey size - } else { - unsafe { bitcoin_pqc_secret_key_size(algorithm.into()) } - } -} - -/// Get the signature size for an algorithm -/// -/// # Arguments -/// -/// * `algorithm` - The algorithm to get the size for -/// -/// # Returns -/// -/// The size in bytes -pub fn signature_size(algorithm: Algorithm) -> usize { - if algorithm == Algorithm::SECP256K1_SCHNORR { - 64 // schnorr::Signature size - } else { - unsafe { bitcoin_pqc_signature_size(algorithm.into()) } - } -} diff --git a/tests/algorithm_tests.rs b/tests/algorithm_tests.rs deleted file mode 100644 index e945e97..0000000 --- a/tests/algorithm_tests.rs +++ /dev/null @@ -1,316 +0,0 @@ -use hex::decode as hex_decode; -use rand::{rng, RngCore}; - -use bitcoinpqc::{ - generate_keypair, public_key_size, secret_key_size, sign, signature_size, verify, Algorithm, -}; - -// Original random data generation function (commented out for deterministic tests) -fn _get_random_bytes_original(size: usize) -> Vec { - let mut bytes = vec![0u8; size]; - rng().fill_bytes(&mut bytes); - bytes -} - -// Function to return fixed test data based on predefined hex strings -// This ensures deterministic test results -fn get_random_bytes(size: usize) -> Vec { - match size { - 128 => { - // Fixed test vectors for key generation (128 bytes) - - // ML-DSA-44 key generation test vector - let ml_dsa_keygen_data = "20739d89b87379e83a915a0764366ed1e72eb307b3c7846dc135933370f00b266277961d536b47026f7eb874603384e3a2b9ea51f033aa4257acd17606d2cd86bc6c2a6745d59dcc148d5a8776be46e127e3ccf57212bd0eef8085aa871cc40b91693fd9a79034504f639cea0e618509afd84d943b3928524becc473c3fa3c2a"; - - // SLH-DSA-128S key generation test vector - let slh_dsa_keygen_data = "dd348981dfba96c006d27d64ad0ae37c9a358e3a03df7e9ffac1519eca12dc3b64bea0144f3536a74d9caba846b7143788e89a2a279a81947364f422d491dcb47925a77be4d551b25a81070e6a460effe30939224240e4f4dc9470d3d99f7312c24523a28128ea448ef47bcc1b0ae637ad6ece2251d3e2d55c0bba6d346ca66b"; - - // Deterministic signing test vectors - - // ML-DSA-44 deterministic signing test vector - let ml_dsa_det_data = "12187a59a14e1e9a0c37fc7625a0d3f8782f1e4cd361751abf7b85745173488e3e19afd47cbd4a823577cb360aed406791558ea1ff217fcd38af566e0e5d4d0903e6ea9c29108393c1a423f41b876b43ce0856ee436866f98d56ec8ceb169ed0470d847608f295474002a91a54937a64ac236fb9cf49fedf60b76500e3c0a7f0"; - - // SLH-DSA-128S deterministic signing test vector - let slh_dsa_det_data = "8ca905fd3e122d02e411683b52ecb1863104793aeba57718aabc9a65db5d61a66ca4bd29376d8118ceb555868b7054b59e23a45538d4ca28ad2080f70c56cce85f1fd5568661cb6ac06a9296ae77d97a7b854dab7eda10a4b78dd3a8f2e741f5c4686278eda9a1ac255a0cdbc79081435161331b69f9cbc04e7ae50cbfbab0ec"; - - // Choose which data to return based on the test context - let thread = std::thread::current(); - let test_name = thread.name().unwrap_or("unknown"); - - let hex_data = if test_name.contains("ml_dsa_44") { - ml_dsa_keygen_data - } else if test_name.contains("slh_dsa_128s") { - slh_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, - _ => slh_dsa_det_data, - }; - COUNTER += 1; - data - } - } else { - // Default to ML-DSA data - ml_dsa_keygen_data - }; - - hex_decode(hex_data).expect("Invalid hex data") - } - 64 => { - // Fixed test vectors for signing (64 bytes) - - // ML-DSA-44 signing test vector - let ml_dsa_sign_data = "8fe682ed84da0fdfa9243c424c864b1d9137c0c87bc8f23dbea9268f3930c8a3778139311c18dadd6a9aea791486f2d7638a7be8f09ca3546580312a8bb95f97"; - - // SLH-DSA-128S signing test vector - let slh_dsa_sign_data = "c2dd94eec866f66b5fe8cbc07cfdbc8b4b92880f4fe53131feb1539323e87f64d3b32fd22375ead15c6c0f5c68323ed343041acfd3d962382b406e9aa30aa45c"; - - // Choose which data to return based on the test context - let thread = std::thread::current(); - let test_name = thread.name().unwrap_or("unknown"); - - let hex_data = if test_name.contains("ml_dsa_44") { - ml_dsa_sign_data - } else if test_name.contains("slh_dsa_128s") { - slh_dsa_sign_data - } else { - // Default to ML-DSA data - ml_dsa_sign_data - }; - - hex_decode(hex_data).expect("Invalid hex data") - } - _ => { - // Fallback for other sizes (e.g., 127 for error condition tests) - // This still uses random data since it's typically for error cases - let mut bytes = vec![0u8; size]; - rng().fill_bytes(&mut bytes); - bytes - } - } -} - -#[test] -fn test_key_sizes() { - // Verify the key and signature sizes are as expected - assert_eq!(public_key_size(Algorithm::ML_DSA_44), 1312); - assert_eq!(secret_key_size(Algorithm::ML_DSA_44), 2560); - assert_eq!(signature_size(Algorithm::ML_DSA_44), 2420); - - 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); -} - -#[test] -fn test_ml_dsa_44_keygen_sign_verify() { - println!("Starting ML-DSA-44 test"); - let random_data = get_random_bytes(128); - println!("Generated random data of size {}", random_data.len()); - - let keypair = generate_keypair(Algorithm::ML_DSA_44, &random_data) - .expect("Failed to generate ML-DSA-44 keypair"); - - println!("Key generation successful"); - - // Verify the key sizes match expected values - assert_eq!( - keypair.public_key.bytes.len(), - public_key_size(Algorithm::ML_DSA_44) - ); - println!("Public key size: {}", keypair.public_key.bytes.len()); - - assert_eq!( - keypair.secret_key.bytes.len(), - secret_key_size(Algorithm::ML_DSA_44) - ); - println!("Secret key size: {}", keypair.secret_key.bytes.len()); - - // Test signing and verification - let message = b"ML-DSA-44 Test Message"; - println!("Message to sign: {message:?}"); - - let signature = sign(&keypair.secret_key, message).expect("Failed to sign with ML-DSA-44"); - - println!( - "Signature created successfully, size: {}", - signature.bytes.len() - ); - println!( - "Signature prefix: {:02x?}", - &signature.bytes[..8.min(signature.bytes.len())] - ); - - // Verify the signature - println!("Verifying signature..."); - let result = verify(&keypair.public_key, message, &signature); - println!("Verification result: {result:?}"); - - assert!(result.is_ok(), "ML-DSA-44 signature verification failed"); - - // Try to verify with a modified message - should fail - let modified_message = b"ML-DSA-44 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(), - "ML-DSA-44 verification should fail with modified message" - ); -} - -#[test] -fn test_slh_dsa_128s_keygen_sign_verify() { - println!("Starting SLH-DSA-128S test"); - let random_data = get_random_bytes(128); - println!("Generated random data of size {}", random_data.len()); - - let keypair = generate_keypair(Algorithm::SLH_DSA_128S, &random_data) - .expect("Failed to generate SLH-DSA-128S keypair"); - - println!("Key generation successful"); - - // Verify the key sizes match expected values - assert_eq!( - keypair.public_key.bytes.len(), - public_key_size(Algorithm::SLH_DSA_128S) - ); - println!("Public key size: {}", keypair.public_key.bytes.len()); - - assert_eq!( - keypair.secret_key.bytes.len(), - secret_key_size(Algorithm::SLH_DSA_128S) - ); - println!("Secret key size: {}", keypair.secret_key.bytes.len()); - - // Test signing and verification - let message = b"SLH-DSA-128S Test Message"; - println!("Message to sign: {message:?}"); - - let signature = sign(&keypair.secret_key, message).expect("Failed to sign with SLH-DSA-128S"); - - println!( - "Signature created successfully, size: {}", - signature.bytes.len() - ); - println!( - "Signature prefix: {:02x?}", - &signature.bytes[..8.min(signature.bytes.len())] - ); - - // Verify the signature - println!("Verifying signature..."); - let result = verify(&keypair.public_key, message, &signature); - println!("Verification result: {result:?}"); - - assert!(result.is_ok(), "SLH-DSA-128S signature verification failed"); - - // Try to verify with a modified message - should fail - let modified_message = b"SLH-DSA-128S 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(), - "SLH-DSA-128S verification should fail with modified message" - ); -} - -#[test] -fn test_deterministic_signing() { - // Test ML-DSA-44 deterministic signing - let random_data = get_random_bytes(128); - let keypair = generate_keypair(Algorithm::ML_DSA_44, &random_data) - .expect("Failed to generate ML-DSA-44 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 ML-DSA-44 signature should be valid" - ); - assert!( - verify(&keypair.public_key, message, &signature2).is_ok(), - "Second ML-DSA-44 signature should be valid" - ); - - // Test SLH-DSA-128S deterministic signing - let random_data = get_random_bytes(128); - let keypair = generate_keypair(Algorithm::SLH_DSA_128S, &random_data) - .expect("Failed to generate SLH-DSA-128S 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 SLH-DSA-128S signature should be valid" - ); - assert!( - verify(&keypair.public_key, message, &signature2).is_ok(), - "Second SLH-DSA-128S signature should be valid" - ); -} - -#[test] -fn test_error_conditions() { - // Test with insufficient random data for key generation for all algorithms - let short_random = get_random_bytes(127); // Need at least 128 bytes - - // Test ML-DSA-44 - let result = generate_keypair(Algorithm::ML_DSA_44, &short_random); - assert!( - result.is_err(), - "ML-DSA-44 should fail with insufficient random data" - ); - - // Test SLH-DSA-128S - let result = generate_keypair(Algorithm::SLH_DSA_128S, &short_random); - assert!( - result.is_err(), - "SLH-DSA-128S 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"); - - // Create message for testing - let message = b"Test message"; - - // 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"); - - // Try to verify with mismatched algorithms - let result = verify(&slh_keypair.public_key, message, &ml_sig); - assert!( - result.is_err(), - "Verification should fail with ML-DSA-44 signature and SLH-DSA-128S key" - ); - - let result = verify(&ml_keypair.public_key, message, &slh_sig); - assert!( - result.is_err(), - "Verification should fail with SLH-DSA-128S signature and ML-DSA-44 key" - ); -} diff --git a/tests/serialization_tests.rs b/tests/serialization_tests.rs deleted file mode 100644 index cc14377..0000000 --- a/tests/serialization_tests.rs +++ /dev/null @@ -1,447 +0,0 @@ -use hex::{decode as hex_decode, encode as hex_encode}; -use rand::{rng, RngCore}; - -use bitcoinpqc::{generate_keypair, sign, verify, Algorithm, PublicKey, SecretKey, Signature}; - -// Original random data generation function (commented out for deterministic tests) -fn _get_random_bytes_original(size: usize) -> Vec { - let mut bytes = vec![0u8; size]; - rng().fill_bytes(&mut bytes); - bytes -} - -// Function to return fixed test data based on predefined hex strings -// This ensures deterministic test results -fn get_random_bytes(size: usize) -> Vec { - match size { - 128 => { - // Single common test vector for all tests (128 bytes) - let random_data = "f47e7324fb639d867a35eea3558a54224e7ca5e357c588c136d2d514facd5fc0d93a31a624a7c3d9ba02f8a73bd2e9dac7b2e3a0dcf1900b2c3b8e56c6efec7ef2aa654567e42988f6c1b71ae817db8f7dbf25c5e7f3ddc87f39b8fc9b3c44caacb6fe8f9df68e895f6ae603e1c4db3c6a0e1ba9d52ac34a63426f9be2e2ac16"; - hex_decode(random_data).expect("Invalid hex data") - } - 64 => { - // Fixed test vector for signing (64 bytes) - let sign_data = "7b8681d6e06fa65ef3b77243e7670c10e7c983cbe07f09cb1ddd10e9c4bc8ae6409a756b5bc35a352ab7dcf08395ce6994f4aafa581a843db147db47cf2e6fbd"; - hex_decode(sign_data).expect("Invalid hex data") - } - _ => { - // Fallback for other sizes - let mut bytes = vec![0u8; size]; - rng().fill_bytes(&mut bytes); - bytes - } - } -} - -#[test] -fn test_public_key_serialization() { - // Generate a keypair with deterministic data - let random_data = get_random_bytes(128); - let keypair = - generate_keypair(Algorithm::ML_DSA_44, &random_data).expect("Failed to generate keypair"); - - // Print public key prefix for informational purposes - let pk_prefix = hex_encode(&keypair.public_key.bytes[0..16]); - println!("ML-DSA-44 Public key prefix: {pk_prefix}"); - - // Check the public key has the expected length - assert_eq!( - keypair.public_key.bytes.len(), - 1312, - "Public key should have the correct length" - ); - - // Check the public key has a non-empty prefix - assert!( - !pk_prefix.is_empty(), - "Public key should have a non-empty prefix" - ); - - // Extract the public key bytes - let pk_bytes = keypair.public_key.bytes.clone(); - - // Create a new PublicKey from the bytes - let reconstructed_pk = PublicKey { - algorithm: Algorithm::ML_DSA_44, - bytes: pk_bytes, - }; - - // Sign a message using the original key - let message = b"Serialization test message"; - let signature = sign(&keypair.secret_key, message).expect("Failed to sign message"); - - // Print signature for informational purposes - println!( - "ML-DSA-44 Signature prefix: {}", - hex_encode(&signature.bytes[0..16]) - ); - - // Verify the signature using the reconstructed public key - let result = verify(&reconstructed_pk, message, &signature); - assert!( - result.is_ok(), - "Verification with reconstructed public key failed" - ); -} - -#[test] -fn test_secret_key_serialization() { - // Generate a keypair with deterministic data - let random_data = get_random_bytes(128); - let keypair = generate_keypair(Algorithm::SLH_DSA_128S, &random_data) - .expect("Failed to generate keypair"); - - // Print key prefixes for diagnostic purposes - let sk_prefix = hex_encode(&keypair.secret_key.bytes[0..16]); - let pk_prefix = hex_encode(&keypair.public_key.bytes[0..16]); - println!("SLH-DSA-128S Secret key prefix: {sk_prefix}"); - println!("SLH-DSA-128S Public key prefix: {pk_prefix}"); - - // Extract the secret key bytes - let sk_bytes = keypair.secret_key.bytes.clone(); - - // Create a new SecretKey from the bytes - let reconstructed_sk = SecretKey { - algorithm: Algorithm::SLH_DSA_128S, - bytes: sk_bytes, - }; - - // Sign a message using the reconstructed secret key - let message = b"Secret key serialization test message"; - let signature = - sign(&reconstructed_sk, message).expect("Failed to sign with reconstructed key"); - - // Print signature for informational purposes - println!( - "SLH-DSA-128S Signature prefix: {}", - hex_encode(&signature.bytes[0..16]) - ); - - // Verify the signature using the original public key - let result = verify(&keypair.public_key, message, &signature); - assert!( - result.is_ok(), - "Verification of signature from reconstructed secret key failed" - ); -} - -#[test] -fn test_signature_serialization() { - // Generate a keypair with deterministic data - let random_data = get_random_bytes(128); - let keypair = - generate_keypair(Algorithm::ML_DSA_44, &random_data).expect("Failed to generate keypair"); - - // Sign a message - let message = b"Signature serialization test"; - let signature = sign(&keypair.secret_key, message).expect("Failed to sign message"); - - // Print signature for informational purposes - println!( - "ML-DSA-44 Signature prefix: {}", - hex_encode(&signature.bytes[0..16]) - ); - - // Create a new Signature from the bytes - let reconstructed_sig = Signature { - algorithm: Algorithm::ML_DSA_44, - bytes: signature.bytes.clone(), - }; - - // Verify that the reconstructed signature bytes match - assert_eq!( - signature.bytes, reconstructed_sig.bytes, - "Reconstructed signature bytes should match original" - ); - - // Verify the reconstructed signature - let result = verify(&keypair.public_key, message, &reconstructed_sig); - assert!( - result.is_ok(), - "Verification with reconstructed signature failed" - ); -} - -#[test] -fn test_cross_algorithm_serialization_failure() { - // Generate keypairs for different algorithms with deterministic data - let random_data = get_random_bytes(128); - let keypair_ml_dsa = generate_keypair(Algorithm::ML_DSA_44, &random_data) - .expect("Failed to generate ML-DSA keypair"); - let keypair_slh_dsa = generate_keypair(Algorithm::SLH_DSA_128S, &random_data) - .expect("Failed to generate SLH-DSA keypair"); - - // Sign with ML-DSA - let message = b"Cross algorithm test"; - let signature = sign(&keypair_ml_dsa.secret_key, message).expect("Failed to sign message"); - - // Print signature for informational purposes - println!( - "ML-DSA signature prefix: {}", - hex_encode(&signature.bytes[0..16]) - ); - - // Attempt to verify ML-DSA signature with SLH-DSA public key - // This should fail because the algorithms don't match - let result = verify(&keypair_slh_dsa.public_key, message, &signature); - assert!( - result.is_err(), - "Verification should fail when using public key from different algorithm" - ); - - // Create an invalid signature by changing the algorithm but keeping the bytes - let invalid_sig = Signature { - algorithm: Algorithm::SLH_DSA_128S, // Wrong algorithm - bytes: signature.bytes.clone(), - }; - - // This should fail because the signature was generated with ML-DSA but claimed to be SLH-DSA - let result = verify(&keypair_slh_dsa.public_key, message, &invalid_sig); - assert!( - result.is_err(), - "Verification should fail with mismatched algorithm" - ); - - // Also verify that the library correctly checks algorithm consistency - let result = verify(&keypair_ml_dsa.public_key, message, &invalid_sig); - assert!( - result.is_err(), - "Verification should fail when signature algorithm doesn't match public key algorithm" - ); -} - -// Add new test for serialization consistency -#[test] -fn test_serialization_consistency() { - // Generate keypairs for each algorithm using deterministic data - let random_data = get_random_bytes(128); - - // ML-DSA-44 - let ml_keypair = generate_keypair(Algorithm::ML_DSA_44, &random_data) - .expect("Failed to generate ML-DSA keypair"); - - // Expected ML-DSA key serialization (from test output) - let expected_ml_pk_prefix = "b3f22d3e1f93e3122063898b98eb89e6"; - let expected_ml_sk_prefix = "b3f22d3e1f93e3122063898b98eb89e6"; - - // Print and verify ML-DSA public key - let actual_ml_pk_prefix = hex_encode(&ml_keypair.public_key.bytes[0..16]); - println!("ML-DSA-44 public key prefix: {actual_ml_pk_prefix}"); - - assert_eq!( - actual_ml_pk_prefix, expected_ml_pk_prefix, - "ML-DSA-44 public key serialization should be deterministic" - ); - - // Print and verify ML-DSA secret key - let actual_ml_sk_prefix = hex_encode(&ml_keypair.secret_key.bytes[0..16]); - println!("ML-DSA-44 secret key prefix: {actual_ml_sk_prefix}"); - - assert_eq!( - actual_ml_sk_prefix, expected_ml_sk_prefix, - "ML-DSA-44 secret key serialization should be deterministic" - ); - - // SLH-DSA-128S - Just print for informational purposes - let slh_keypair = generate_keypair(Algorithm::SLH_DSA_128S, &random_data) - .expect("Failed to generate SLH-DSA keypair"); - - println!( - "SLH-DSA-128S public key prefix: {}", - hex_encode(&slh_keypair.public_key.bytes[0..16]) - ); - println!( - "SLH-DSA-128S secret key prefix: {}", - hex_encode(&slh_keypair.secret_key.bytes[0..16]) - ); - - // Test serialization/deserialization consistency - let message = b"Serialization consistency test"; - - // ML-DSA-44 signature consistency - let ml_sig = sign(&ml_keypair.secret_key, message).expect("Failed to sign with ML-DSA-44"); - - // Print ML-DSA signature for informational purposes - println!( - "ML-DSA-44 signature prefix: {}", - hex_encode(&ml_sig.bytes[0..16]) - ); - - // Verify keys generated with the same random data are consistent - let new_ml_keypair = generate_keypair(Algorithm::ML_DSA_44, &random_data) - .expect("Failed to generate second ML-DSA-44 keypair"); - - assert_eq!( - hex_encode(&ml_keypair.public_key.bytes), - hex_encode(&new_ml_keypair.public_key.bytes), - "ML-DSA-44 public key generation should be deterministic" - ); - - assert_eq!( - hex_encode(&ml_keypair.secret_key.bytes), - hex_encode(&new_ml_keypair.secret_key.bytes), - "ML-DSA-44 secret key generation should be deterministic" - ); -} - -// // Add new test for serde roundtrip serialization/deserialization -// #[cfg(feature = "serde")] -// #[test] -// fn test_serde_roundtrip() { -// // Use deterministic random data -// let random_data = get_random_bytes(128); -// let message = b"Serde roundtrip test message"; - -// // Test each algorithm -// for algorithm in [Algorithm::ML_DSA_44, Algorithm::SLH_DSA_128S].iter() { -// // Generate keypair -// let keypair = generate_keypair(*algorithm, &random_data) -// .unwrap_or_else(|_| panic!("Failed to generate keypair for {algorithm:?}")); - -// // Sign message -// let signature = sign(&keypair.secret_key, message) -// .unwrap_or_else(|_| panic!("Failed to sign message for {algorithm:?}")); - -// // --- PublicKey Test --- -// let pk_json = serde_json::to_string_pretty(&keypair.public_key) -// .expect("Failed to serialize PublicKey"); // Use pretty print for readability - -// // Define the expected fixture (UPDATE THIS STRING) -// let expected_pk_json = match *algorithm { -// Algorithm::ML_DSA_44 => { -// r#"{ -// "algorithm": "ML_DSA_44", -// "bytes": "b3f22d3e1f93e3122063898b98eb89e65278d56bd6e81478d0f45dbd94640febdec294921bd45b3bea23bc1d0158e1e34daf4c82e734524d505d10fa6113285e726ac719246cc34d032fd1e16c85821597acd5452af5a87e5fc84d8c5f332c839c0cd9d48b1dfa47352976ad7835e36577fdb30126c28ce2d214584ee2dbc2ca8a40499c02442015268800312090890b331250b40ccc8869031210910411d1c4501b24121b060a8b126cc80265e0364294184d99c464cc2866d2326998486601894880b06d984891a0142119491104106c5384450a05625c100a2421508c021049944192b22da422681aa2049c002202478810134618113224983081c20c1a1500212191db984d0b488164868d61308804298421a630d4340a984449c0426002a690c04249031721821802901091843820d2b41010c529e02405e3342823164111099192800123161220c925029785181728e1c6891b883181c6655c488249b64009a07082802dc042692422310b804411142264203111456c1c308104220a4b16801b432401a169032832d98209531489e4123198c001449631a2486119924c1c258444008d4232860316642147060c272821b70021266ae3c67122b760102170109808a444294b900823b1704a8040d4188611b0091c24001218669a82419b0060d3c04cd9400dca4471221724003846981461c9962dd038401022851345729b304622b8044a0461d186651895805936698aa27091802c928000cc8811c94885003389098021994680a3a251942652c9426c9ac669d38890910661cb9270211300c41884e190400a1062e11841d2245160308e59064a94908899b83123956454c28801c060c4868d5a948850806004463199880852960c60208021b94519366d0189051b086624328d89c26da11865203428d8a45041b8896498711c450e621468024290c194301a990c5916711a05304112280027210b2741c4c289d39465c3365240c850e0c04114444a64203109884114a13154902844c88001c26493807193a49101c6082003266146529c28110c12024c4088c9b00d1ac08153464013a88010426c08890823271290b62091228a6418458ba0641c272acc8630e0486d0ca371d3868da0168e48a23062800580142189b268a2884d0c373214038090c4711b477258002e64026a1aa12d00c8245b98684844019a004149026d10a08d82840012b45102435221a32d5b908c648290939250023986081711212905dcc2619d5be95a339c1bc29c0538fe02924c096b7c7063deb34148fc2ac4297d5f2e85aea1ef57e1236204f75c6264559eb6f933df5b55302d09d6c6cb889fd44508a2122accc2b3cc2a0699147ec848a846c37c33f55dad55aff5de196966d3d01f71aca8fbb72c9d9018e0830a5eb3424bccae6288c13558faf85f1b8f095365a6c7d3b699f9a6332a377b12498df39a595fe1265eb04f10c81b826aed2a266bab5d2ce07020395961fd6358cbabde2264c6083cda237f13db7481d6100b46480bef4652c786871196fec4564a96ab056f8c15586b351391a6d808c9e7f4359a1499f8f07d99aad4e589a25be4e617ab70b39ba9eed53aaec3a4bc400e294d7eed7583489cd5cf6ae450fafe2db09098fd0a8ccc68e4d2b77064874501daf62757daf653365acfaca2df2280520f8374ac8d5e84b6a43f98f4afae4f84413c030ec7f21cf0e8a7d23b5d12654f7364460c5d8b4c75f790e3ba538c2e3f776b2769b794f45d1e1aac14febcb24eb335afac4154a73dd4435ebb9d5326d74dfaf349e44d88703c08748d6c850d4107990f0a18fecf2beebb88123894d489cbfe0c26fb88ca76a89ab233fec7a5cbb8566145c0a4a3a0d86f9e9689e5450f90d3a099870cea373243793ca3e5a92ff916f935fabacda0bf6bd8977b1bcf36f52f7812645e615f26e7df37c7278da16e8024d9027673f942fd7b8d738b525a629f1ba6ac66779db0bd8c90ab3903f7e9047f66b21dac94a9c335fe6aa78c6927663c0a74c89550bdc9d8201127984aa89ee2b80728be9b3f0d54a73172ba2ea4d1f7c4804af6998f8cd081d2e04b5448d2952749e09dae4354b893f26d355635d20764055e30459c613bb32fdb4ae074f545deafb3c532aac9559c8d3674cd132e4f854f1d9aab8c23bc94a0269a61b0f3d0b5ac3afb1ea35a45aca151ec63ec5bcc02ca647f2982c205549a2c8a5382ddd0c9e06ce545a18718a1bcea27623814bd3a8ce3b8ff8494f89cc32e05bd5749daa63b894685ce6906dfbfc411c2917d4b35fed903d8dc22a3056c28438c772c592d850a4d58becf2a286ed2e72f4ec13835236b3734367ea0b0f2eb38eff07c87d69fc4c7e86dd135459da3c96aa34400ca2db9eac2018a6a9c8d1339b6752023df35e1bb97b44555d194bae18232f68d2206fc35ba3754a33c91e82819c62ef864166910c7e40ed375647069d98fe7805e75e285a160a7950348304791208d4d82c5410ea019c39076ec36e8ed9a4d3eb87dac7eb3067b5776535301d2c622e7fa67a13d70cc4450c3093c5a47689e90a1b4178ccde8719baed1d3a2630078740a502977474b7025abdcb7998ec442d5aea31d6a8533aacff0111f935de36dfc6e266701d7c3778e7f4ebfa6f7ff9e6b1fab8962f30e5276b2a76f20acbf7087bd2d092dbf642843fa980f8a4b80ce730902c0e637f6c480f1f441ee731c9fa4d33258d00ff47be9b413eb176ac1cbc0c06edf67a59f9a996f9175327de3b829d1d830a638bf6056a87ec4150b440440a2ef9e5bafcdcedf4753ff11b1f2b00e52070f4984af34cefd224f36e6d04358418b05e52ed089dac28aac67c0e4d0ab79e4ee82377c9c4ceda877dcdc2fad48a88ae1fe4cc2582f1e41b5d557897902435a27a9bffc63357135c7e6e60516f56dccbd412afb250f117cbfa234619d75f199e397c587c523e4942728cd7d4d59aca9b52fa9364a7b81d9fd7c23e688b04bdaa986e21d7dbfcbfa634b8fcdfa2619d9b6904e3d8e3205bbf5a3d526c4bf9017723fa8944a0b08595e5252e361c5a353ae737177f043e9c2460f48a8aadbd342d773ad6e034191763d87e8c33a3a443cba0174f0bc49385b5a6ca75bb7c000888dcef43bc22252eac9710afb4a6c7a63b363d08e083e691aa848cad7bec731067a1a90a7803328aed4c987eb586461a523ab8fbda4829511f7a427940b94351966c8cb37dc22dd34a81c0542adeb97fff1f1460e72c575c9d18c571ae7175a9ce269fc570c0945484e6e5fca628b5bf0904bad7027e691f1fc8d740ed172fe8816b06b7a672d67faffa91affad41828204d5dbc10c68edbe911131c6f8993c054a2165675794bf6dd1b617a9e5fca0a1a884b21d236163c559be4daf02d5ed54034f735fb031bc17e95066ab3ac9120fd24e238e6255f5ae72fe81c0f9fb69979c746b893421842aa7641d50ff2b2506d078b0aeee703f08223be66255e62fa568a244ef8642eda22ca33472c07e3d8398fe12dae1dcb37dab68aca08a8aa439c4f2257910a0f46af5bcbdad3f987c17ac6c52703a04705ed920c69526fc748f366974706d19143cef2c3441ffa01e06" -// }"# -// } -// Algorithm::SLH_DSA_128S => { -// r#"{ -// "algorithm": "SLH_DSA_128S", -// "bytes": "f47e7324fb639d867a35eea3558a54224e7ca5e357c588c136d2d514facd5fc0d93a31a624a7c3d9ba02f8a73bd2e9dad0261c237a3fa1df610b30f2a06bc750" -// }"# -// } -// _ => panic!("Fixture missing for algorithm {algorithm:?}"), -// }; - -// println!("Algorithm: {algorithm:?}, Generated PublicKey JSON:\n{pk_json}"); // Print generated JSON to help update fixtures -// assert_eq!( -// pk_json, -// serde_json::to_string_pretty( -// &serde_json::from_str::(expected_pk_json).unwrap() -// ) -// .unwrap(), // Compare pretty formats -// "PublicKey JSON does not match fixture for {algorithm:?}" -// ); - -// // Roundtrip check (still useful) -// let reconstructed_pk: PublicKey = -// serde_json::from_str(&pk_json).expect("Failed to deserialize PublicKey"); -// assert_eq!( -// keypair.public_key, reconstructed_pk, -// "PublicKey roundtrip failed for {algorithm:?}" -// ); - -// // --- SecretKey Test --- -// let sk_json = serde_json::to_string_pretty(&keypair.secret_key) -// .expect("Failed to serialize SecretKey"); - -// // Define the expected fixture (UPDATE THIS STRING) -// let expected_sk_json = match *algorithm { -// Algorithm::ML_DSA_44 => { -// r#"{ -// "algorithm": "ML_DSA_44", -// "bytes": "b3f22d3e1f93e3122063898b98eb89e65278d56bd6e81478d0f45dbd94640febdec294921bd45b3bea23bc1d0158e1e34daf4c82e734524d505d10fa6113285e726ac719246cc34d032fd1e16c85821597acd5452af5a87e5fc84d8c5f332c839c0cd9d48b1dfa47352976ad7835e36577fdb30126c28ce2d214584ee2dbc2ca8a40499c02442015268800312090890b331250b40ccc8869031210910411d1c4501b24121b060a8b126cc80265e0364294184d99c464cc2866d2326998486601894880b06d984891a0142119491104106c5384450a05625c100a2421508c021049944192b22da422681aa2049c002202478810134618113224983081c20c1a1500212191db984d0b488164868d61308804298421a630d4340a984449c0426002a690c04249031721821802901091843820d2b41010c529e02405e3342823164111099192800123161220c925029785181728e1c6891b883181c6655c488249b64009a07082802dc042692422310b804411142264203111456c1c308104220a4b16801b432401a169032832d98209531489e4123198c001449631a2486119924c1c258444008d4232860316642147060c272821b70021266ae3c67122b760102170109808a444294b900823b1704a8040d4188611b0091c24001218669a82419b0060d3c04cd9400dca4471221724003846981461c9962dd038401022851345729b304622b8044a0461d186651895805936698aa27091802c928000cc8811c94885003389098021994680a3a251942652c9426c9ac669d38890910661cb9270211300c41884e190400a1062e11841d2245160308e59064a94908899b83123956454c28801c060c4868d5a948850806004463199880852960c60208021b94519366d0189051b086624328d89c26da11865203428d8a45041b8896498711c450e621468024290c194301a990c5916711a05304112280027210b2741c4c289d39465c3365240c850e0c04114444a64203109884114a13154902844c88001c26493807193a49101c6082003266146529c28110c12024c4088c9b00d1ac08153464013a88010426c08890823271290b62091228a6418458ba0641c272acc8630e0486d0ca371d3868da0168e48a23062800580142189b268a2884d0c373214038090c4711b477258002e64026a1aa12d00c8245b98684844019a004149026d10a08d82840012b45102435221a32d5b908c648290939250023986081711212905dcc2619d5be95a339c1bc29c0538fe02924c096b7c7063deb34148fc2ac4297d5f2e85aea1ef57e1236204f75c6264559eb6f933df5b55302d09d6c6cb889fd44508a2122accc2b3cc2a0699147ec848a846c37c33f55dad55aff5de196966d3d01f71aca8fbb72c9d9018e0830a5eb3424bccae6288c13558faf85f1b8f095365a6c7d3b699f9a6332a377b12498df39a595fe1265eb04f10c81b826aed2a266bab5d2ce07020395961fd6358cbabde2264c6083cda237f13db7481d6100b46480bef4652c786871196fec4564a96ab056f8c15586b351391a6d808c9e7f4359a1499f8f07d99aad4e589a25be4e617ab70b39ba9eed53aaec3a4bc400e294d7eed7583489cd5cf6ae450fafe2db09098fd0a8ccc68e4d2b77064874501daf62757daf653365acfaca2df2280520f8374ac8d5e84b6a43f98f4afae4f84413c030ec7f21cf0e8a7d23b5d12654f7364460c5d8b4c75f790e3ba538c2e3f776b2769b794f45d1e1aac14febcb24eb335afac4154a73dd4435ebb9d5326d74dfaf349e44d88703c08748d6c850d4107990f0a18fecf2beebb88123894d489cbfe0c26fb88ca76a89ab233fec7a5cbb8566145c0a4a3a0d86f9e9689e5450f90d3a099870cea373243793ca3e5a92ff916f935fabacda0bf6bd8977b1bcf36f52f7812645e615f26e7df37c7278da16e8024d9027673f942fd7b8d738b525a629f1ba6ac66779db0bd8c90ab3903f7e9047f66b21dac94a9c335fe6aa78c6927663c0a74c89550bdc9d8201127984aa89ee2b80728be9b3f0d54a73172ba2ea4d1f7c4804af6998f8cd081d2e04b5448d2952749e09dae4354b893f26d355635d20764055e30459c613bb32fdb4ae074f545deafb3c532aac9559c8d3674cd132e4f854f1d9aab8c23bc94a0269a61b0f3d0b5ac3afb1ea35a45aca151ec63ec5bcc02ca647f2982c205549a2c8a5382ddd0c9e06ce545a18718a1bcea27623814bd3a8ce3b8ff8494f89cc32e05bd5749daa63b894685ce6906dfbfc411c2917d4b35fed903d8dc22a3056c28438c772c592d850a4d58becf2a286ed2e72f4ec13835236b3734367ea0b0f2eb38eff07c87d69fc4c7e86dd135459da3c96aa34400ca2db9eac2018a6a9c8d1339b6752023df35e1bb97b44555d194bae18232f68d2206fc35ba3754a33c91e82819c62ef864166910c7e40ed375647069d98fe7805e75e285a160a7950348304791208d4d82c5410ea019c39076ec36e8ed9a4d3eb87dac7eb3067b5776535301d2c622e7fa67a13d70cc4450c3093c5a47689e90a1b4178ccde8719baed1d3a2630078740a502977474b7025abdcb7998ec442d5aea31d6a8533aacff0111f935de36dfc6e266701d7c3778e7f4ebfa6f7ff9e6b1fab8962f30e5276b2a76f20acbf7087bd2d092dbf642843fa980f8a4b80ce730902c0e637f6c480f1f441ee731c9fa4d33258d00ff47be9b413eb176ac1cbc0c06edf67a59f9a996f9175327de3b829d1d830a638bf6056a87ec4150b440440a2ef9e5bafcdcedf4753ff11b1f2b00e52070f4984af34cefd224f36e6d04358418b05e52ed089dac28aac67c0e4d0ab79e4ee82377c9c4ceda877dcdc2fad48a88ae1fe4cc2582f1e41b5d557897902435a27a9bffc63357135c7e6e60516f56dccbd412afb250f117cbfa234619d75f199e397c587c523e4942728cd7d4d59aca9b52fa9364a7b81d9fd7c23e688b04bdaa986e21d7dbfcbfa634b8fcdfa2619d9b6904e3d8e3205bbf5a3d526c4bf9017723fa8944a0b08595e5252e361c5a353ae737177f043e9c2460f48a8aadbd342d773ad6e034191763d87e8c33a3a443cba0174f0bc49385b5a6ca75bb7c000888dcef43bc22252eac9710afb4a6c7a63b363d08e083e691aa848cad7bec731067a1a90a7803328aed4c987eb586461a523ab8fbda4829511f7a427940b94351966c8cb37dc22dd34a81c0542adeb97fff1f1460e72c575c9d18c571ae7175a9ce269fc570c0945484e6e5fca628b5bf0904bad7027e691f1fc8d740ed172fe8816b06b7a672d67faffa91affad41828204d5dbc10c68edbe911131c6f8993c054a2165675794bf6dd1b617a9e5fca0a1a884b21d236163c559be4daf02d5ed54034f735fb031bc17e95066ab3ac9120fd24e238e6255f5ae72fe81c0f9fb69979c746b893421842aa7641d50ff2b2506d078b0aeee703f08223be66255e62fa568a244ef8642eda22ca33472c07e3d8398fe12dae1dcb37dab68aca08a8aa439c4f2257910a0f46af5bcbdad3f987c17ac6c52703a04705ed920c69526fc748f366974706d19143cef2c3441ffa01e06" -// }"# -// } -// Algorithm::SLH_DSA_128S => { -// r#"{ -// "algorithm": "SLH_DSA_128S", -// "bytes": "f47e7324fb639d867a35eea3558a54224e7ca5e357c588c136d2d514facd5fc0d93a31a624a7c3d9ba02f8a73bd2e9dad0261c237a3fa1df610b30f2a06bc750" -// }"# -// } -// _ => panic!("Fixture missing for algorithm {algorithm:?}"), -// }; - -// println!("Algorithm: {algorithm:?}, Generated SecretKey JSON:\n{sk_json}"); -// assert_eq!( -// sk_json, -// serde_json::to_string_pretty( -// &serde_json::from_str::(expected_sk_json).unwrap() -// ) -// .unwrap(), -// "SecretKey JSON does not match fixture for {algorithm:?}" -// ); - -// // Roundtrip check -// let reconstructed_sk: SecretKey = -// serde_json::from_str(&sk_json).expect("Failed to deserialize SecretKey"); -// assert_eq!( -// keypair.secret_key, reconstructed_sk, -// "SecretKey roundtrip failed for {algorithm:?}" -// ); - -// // --- Signature Test --- -// let sig_json = -// serde_json::to_string_pretty(&signature).expect("Failed to serialize Signature"); - -// // Only check fixture for deterministic algorithms -// if *algorithm != Algorithm::SLH_DSA_128S { -// // Define the expected fixture (UPDATE THIS STRING) -// let expected_sig_json = match *algorithm { -// Algorithm::ML_DSA_44 => { -// r#"{ -// "algorithm": "ML_DSA_44", -// "bytes": "d44770409f4dacafbc779f68ef129f8f15138a5befa38a9ced36031ebae7bdcbb09e900350de29cf4b9c2ce04e41bfb40739dd9bd985ed1bbed4c9c7bc96cca6f4d0c921b43b8e4067789b6e7744e7a055a5edc5b4bf0d8fc5ec404c980b5b298e5d930df3375b7ab686177c99ec4be848ce7cc162adb578896d11d4fcc5f0cf1af5f9ad070ea6f3460c06627f937782aaa185304c068748ee86c91fec03853a7ce81a304fcc2afcbb66c2e308af5269cd1c9b45a2ab73d04474d96b1c5890947485dd6c3d6e7bdc7b8e445fb27fb525677b2a3b95954dfd3bb163985d4640a4c1c1102452341e4ad5cbf5b8eb4d30c3323a6572502670e748cddca9d18f12d3a3fffcfec7099f16f6542eb39d3032094023649de67af9ee8e06c9a53cc926388345d6a9412d2de82a4e59c6c11b6f3b259243e45ee57ccd2e4f3a68a8e53b808911b4afe9d72891ca40739e1ab7142ca935e161a19dedf234ed27a7c18ba722780dd53aefc40e921ff0de9ca3ed37ebbe02237f802ea073f11c1b2ef2b703d65739b1d8c060d62a834138d7a2e663854ac794999c95360d849f57b00c37f1cf90a13e0b831df1ada26742097b6465bd2755794e20271077b80ac4d2aa6b5c8e3c77c34ee574dace472eee5eb88b0c59209bb6081a63e3cd9280b4d766e00da79af6d496c90b3ae5800397ecabcaa94d80e765b016a250dddc227d2fd1f6342290cc4ed53d1416fca988cb3d4577e27d76bbd1adcc6b22e80bf9d5901ab5797081012e4fddd320238f5ebf4c4dc5cb17ca57cc76089c8fe54ac7b3bd909ffd37ab4440c4716bb1ea42582c12b195ec38f5654146476bb72bead204fc250671567098ef2fc7c63c111a8cd3abdc5ab6aa4ff47ba5e2998e2aa4950f0725c4c770f974e7e16975068ece9b81e76fe65c84134f31855d910bb2f8ce6de08b59c6020b9292913a6322757176bdb70d2a01428161cc4f858b777d0af656366aaab65bd54cf2ed7820c26f93152cc7e827e403b71a10863409e75dbfb450618c718c3d0ac6b6686f3efc41c07a226547fa21721aeacf09b9707cedca25624f17b52a9fbb80045b62099d31f71dffa551af1d7a7276aed9036939f6c04884d13db33783adfbdd9de05824f6fe2cfbadeecf0e318f1e34bfc03d5a70c4dc8c9cebe1c1b9b605d421144a3d66b7d86710a2b87171680569222480db421b1bd678999d22aa561c55942fd7c2a7900759ee095ed2213d6ed0b5354846a010328f81600b42949be02f48fce7caf64a03dcc97edadc42ef4971f5371ff3e520d2c1de923c0dac6439c3a7e9dd4e55090584f9e2eeea96f29b69417673a8e150efe779166ba498f4ec58b9ecd00aac8b01dff155f29750852fe2e30cb0d6378b1a17ce9d90b93a5c838bbea80cedeb609c600f3bb44314a8c36713c849ec47a3794f3b828b7a8f169f33f3a1eb6867ba5d1fb71e658e1709dd08ac7e874ef3b2077edf570eb3d3989874d729aea331e03caa07ba672bc6b512a7902557bea55ee5466205064193de95ff92d2f5fac41d914e6c7e6fc62cbfe5b9ada3383a502c391782374a1b1241c7368598492f48085aea05f065213f13d9463c4b144e80a426fa5c415e593bef0b541068a8ffa1464e9b8f4ded4da5caad827142778a17d119c3e7121020ff452aefaf816c7ebf190b684d43e2c5547cece9eb7fa4f5312b19fae7f2645ff38c6c9a2514fdfdb74d3ec40e93402027f5af826aaa6c076dc1815b0b7425d5c9f7880f0e82258ff88cc3090e561524bab84bd167840463802df66a18340d7d0ef438a5c99c788ab7f07aaa2ee6e37ae0488967600421e6ddcde2a44dd3ceec3e8914f7fb5a1a42c38e20c1666ccfad1a1ae0364cc85a5612f35e087c77c0c212099c4a60138cb9486a571a59a9993ee00abd77902b684163b50fb02373baa75834ac3638a6c8e6a6038ce2a907c6ba2647cbd3437fb4920b1a5d46fb04b2c36a8aee0f3fcae7709e4508d2c7cfdfb724483dc71881a385eecd8b4dc32f793037be625a8427690ddbd6e0e8d80a15516cbadba4034d6700cb6ec807815f6dd5e8619a336bab503cfe6473cc913a80f9e5897ea68f2866ef145a3f1ef371ebe1151a4a93eceb3059a27fa93a309363b8b23cbf401dff0134a6080805837ae9fcff26a58e86ce37ded0d08f7022a979f0f788e99e7cdf32f16e09282b61d4528c5b79a38feeedf210722a20a428ae5b404c7923d1fa10e790b166b98ab1e44ae6fa3612a723045d7c4b77570345f7e7204227433611644a2c75715184da36f0688fd406c878773c58646bb130146f7ec75f8b03c97eb4329c942d9d6006bd1fcbb4e9f56031191d00334ca77cf71bb895521ea7ba6f9c4d9b67f7c4fd38f4e914cbb9717dac45c802234505de0951f8d897365002feac6dcc8616bab1ec0583de1c3cbbbaab3cbd5db94ff2721c9a22541e6796fca0a217f4eee5e1441398a1286b4638533d4a455f3c83c85d886911072eb45c808306514ef4ad1c31e3e5f7151dab4d2d18ec8ac812e0c03c86d879865281cfa517b955c1842c7e093e35b107eda832356e2992adaa697565e2c4a8e9994767a9a61d717dd2a860695c83ea2c5b5f692493e79f2c184df7db7973dfd79abf00f042ba10ad9ade75ea1b01b62efcebc6a2c7b59a2af01b8691855919b1826799f0bba13509f5db2cb55e3f7c7f72eec95df0da8021ebbbb60d2f063c4129fcd9ed825d8671bb913b4b9cf91e148d941590536a44511b62296be5222a253a19c9293126b5e8b1aebb7a58c4353fced6f23c35f7414730e78024b7ba2f8bfead124bed379d4098a3be2abd3cc10a47fd0fdb40b35ec517fbc66bf2c06e1f6960f8595452705339cdda9a9b5102b8a1a5c1f1f872d0fc564555cc431f95b7ac24fb679188f4d49a94a20f6734c20acc0c7a2463e4eb23350d386198c086818f6ddf32d5842f41d7ef3f1644f76dc401f41e87027aa77671132e3d6faa099f1e28b10d4642fe3364cd82b4950211d741392454d5b395dbf89745cdcf43910add671639829495ceca0b0d6fb2c85a9a3369cc6228ab65d88198167de7519a4857d9f2a5b37b88f4258f9d01780f23174eb9c0b3cbc888e59144c3ccfcef165f6ebe1be85a73976bcb54ba95966299e6eeeeb8fbfc51ce86075a672107e84a56c61a00ebb08e579407da3651fcec5c515ca4a5e49a51fbb07915356b0fc1654a86be032fe6ca14a0ae2526b5c78c04c842ce586a85aa1dd7a80cf355af293be254236c9952f8b1a2f2663613154a74754d0913181d2324272f3d4b577285868999abb5b9bcc5d3dde9f5fbfc050e51595eadf0f1f3273d415e6069799da1b7babfc8c9cdd1d6e7f90a16313345465d7677aeafb5c8ced4ecfb00000000000000001b243748" -// }"# -// } -// // Add cases for other deterministic algorithms like SECP256K1_SCHNORR if needed -// _ => panic!("Fixture check not applicable for algorithm {algorithm:?}"), -// }; - -// println!("Algorithm: {algorithm:?}, Generated Signature JSON:\n{sig_json}"); -// // Compare generated JSON with the pretty-printed version of the parsed fixture -// assert_eq!( -// sig_json, -// serde_json::to_string_pretty( -// &serde_json::from_str::(expected_sig_json).unwrap() -// ) -// .unwrap(), -// "Signature JSON does not match fixture for {algorithm:?}" -// ); -// } else { -// println!("Skipping fixture check for non-deterministic SLH_DSA_128S signature."); -// } - -// // Roundtrip check (always perform this) -// let reconstructed_sig: Signature = -// serde_json::from_str(&sig_json).expect("Failed to deserialize Signature"); -// assert_eq!( -// signature, reconstructed_sig, -// "Signature roundtrip failed for {algorithm:?}" -// ); - -// // --- Verification Tests --- -// // Verify reconstructed signature with reconstructed public key -// let result1 = verify(&reconstructed_pk, message, &reconstructed_sig); -// assert!( -// result1.is_ok(), -// "Verification failed: reconstructed_pk with reconstructed_sig for {algorithm:?}" -// ); - -// // Verify original signature with reconstructed public key -// let result2 = verify(&reconstructed_pk, message, &signature); -// assert!( -// result2.is_ok(), -// "Verification failed: reconstructed_pk with original signature for {algorithm:?}" -// ); - -// // Verify reconstructed signature with original public key -// let result3 = verify(&keypair.public_key, message, &reconstructed_sig); -// assert!( -// result3.is_ok(), -// "Verification failed: original public_key with reconstructed_sig for {algorithm:?}" -// ); - -// println!("Serde roundtrip test passed for {algorithm:?}"); -// } -// } From 4effcbb6a56a08ef99a8dc3619e2f87daa48257b Mon Sep 17 00:00:00 2001 From: jbride Date: Thu, 19 Feb 2026 13:09:04 -0700 Subject: [PATCH 7/7] README: added section regarding entropy length requirement --- README.md | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 47a8835..c72d35c 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,11 @@ This library serves as the cryptographic foundation for the Bitcoin QuBit soft f ## Key Characteristics -| Algorithm | Public Key Size | Secret Key Size | Signature Size | Security Level | -|-----------|----------------|----------------|----------------|----------------| -| secp256k1 | 32 bytes | 32 bytes | 64 bytes | Classical | -| 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 | +| Algorithm | Public Key Size | Secret Key Size | Signature Size | Security Level | +| ------------------ | --------------- | --------------- | -------------- | -------------- | +| secp256k1 | 32 bytes | 32 bytes | 64 bytes | Classical | +| 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 | ## Security Notes @@ -33,6 +33,37 @@ This library serves as the cryptographic foundation for the Bitcoin QuBit soft f - 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. +## Entropy length requirement + +The API requires a minimum of **128 bytes** of entropy for key generation, enforced uniformly +across all algorithms regardless of their individual seed sizes: + +```c +if (!keypair || !random_data) return BITCOIN_PQC_ERROR_BAD_ARG; +if (random_data_size < 128) return BITCOIN_PQC_ERROR_BAD_ARG; +``` + +The actual entropy consumed by each algorithm is less than this minimum: + +| Algorithm | Bytes consumed | Source in spec | +| ------------------ | -------------- | ----------------------------------------------------------------------------------- | +| ML-DSA-44 | 32 bytes | FIPS 204 — one `SEEDBYTES`-wide draw fed into SHAKE-256 expansion | +| SLH-DSA-SHAKE-128s | 48 bytes | FIPS 205 — three independent *n*-byte values (SK.seed ‖ SK.prf ‖ PK.seed), *n* = 16 | + +Bytes beyond these amounts are accepted but **silently ignored** by the underlying +reference implementations. A caller reading the 128-byte requirement should not infer +that all 128 bytes contribute to key material — only the first 32 or 48 bytes (depending +on algorithm) do. + +The 128-byte floor is a deliberate policy choice rather than a per-algorithm technical +requirement, motivated by: + +- **Uniform API** — callers do not need to know per-algorithm seed sizes. +- **Quality signal** — a caller that can supply 128 bytes from a secure source is less + likely to be misusing a low-entropy value padded to the minimum. +- **Headroom** — a future algorithm in the same API could require more entropy without + a breaking change to the interface contract. + ## BIP-360 Compliance This library implements the cryptographic primitives required by [BIP-360](https://github.com/bitcoin/bips/blob/master/bip-0360.mediawiki), which defines the standard for post-quantum resistant signatures in Bitcoin. It supports all three recommended algorithms with the specified parameter sets.