diff --git a/.CMake/alg_support.cmake b/.CMake/alg_support.cmake
index bdd4d94ce..9fdf37cb1 100644
--- a/.CMake/alg_support.cmake
+++ b/.CMake/alg_support.cmake
@@ -169,6 +169,26 @@ cmake_dependent_option(OQS_ENABLE_SIG_mayo_1 "" ON "OQS_ENABLE_SIG_MAYO" OFF)
cmake_dependent_option(OQS_ENABLE_SIG_mayo_2 "" ON "OQS_ENABLE_SIG_MAYO" OFF)
cmake_dependent_option(OQS_ENABLE_SIG_mayo_3 "" ON "OQS_ENABLE_SIG_MAYO" OFF)
cmake_dependent_option(OQS_ENABLE_SIG_mayo_5 "" ON "OQS_ENABLE_SIG_MAYO" OFF)
+
+option(OQS_ENABLE_SIG_CROSS "Enable cross algorithm family" ON)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_128_balanced "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_128_fast "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_128_small "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_192_balanced "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_192_fast "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_192_small "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_256_balanced "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_256_fast "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_256_small "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_128_balanced "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_128_fast "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_128_small "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_192_balanced "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_192_fast "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_192_small "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_256_balanced "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_256_fast "" ON "OQS_ENABLE_SIG_CROSS" OFF)
+cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_256_small "" ON "OQS_ENABLE_SIG_CROSS" OFF)
##### OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ENABLE_BY_ALG_END
##### OQS_COPY_FROM_LIBJADE_FRAGMENT_ADD_ENABLE_BY_ALG_START
@@ -197,7 +217,7 @@ elseif (${OQS_ALGS_ENABLED} STREQUAL "STD")
elseif(${OQS_ALGS_ENABLED} STREQUAL "NIST_R4")
filter_algs("KEM_classic_mceliece_348864;KEM_classic_mceliece_348864f;KEM_classic_mceliece_460896;KEM_classic_mceliece_460896f;KEM_classic_mceliece_6688128;KEM_classic_mceliece_6688128f;KEM_classic_mceliece_6960119;KEM_classic_mceliece_6960119f;KEM_classic_mceliece_8192128;KEM_classic_mceliece_8192128f;KEM_hqc_128;KEM_hqc_192;KEM_hqc_256;KEM_bike_l1;KEM_bike_l3;KEM_bike_l5")
elseif(${OQS_ALGS_ENABLED} STREQUAL "NIST_SIG_ONRAMP")
- filter_algs("SIG_mayo_1;SIG_mayo_2;SIG_mayo_3;SIG_mayo_5")
+ filter_algs("SIG_mayo_1;SIG_mayo_2;SIG_mayo_3;SIG_mayo_5;SIG_cross_rsdp_128_balanced;SIG_cross_rsdp_128_fast;SIG_cross_rsdp_128_small;SIG_cross_rsdp_192_balanced;SIG_cross_rsdp_192_fast;SIG_cross_rsdp_192_small;SIG_cross_rsdp_256_balanced;SIG_cross_rsdp_256_fast;SIG_cross_rsdp_256_small;SIG_cross_rsdpg_128_balanced;SIG_cross_rsdpg_128_fast;SIG_cross_rsdpg_128_small;SIG_cross_rsdpg_192_balanced;SIG_cross_rsdpg_192_fast;SIG_cross_rsdpg_192_small;SIG_cross_rsdpg_256_balanced;SIG_cross_rsdpg_256_fast;SIG_cross_rsdpg_256_small")
else()
message(STATUS "Alg enablement unchanged")
endif()
@@ -531,6 +551,79 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
endif()
endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_128_balanced_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdp_128_balanced" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_128_fast_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdp_128_fast" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_128_small_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdp_128_small" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_192_balanced_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdp_192_balanced" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_192_fast_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdp_192_fast" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_192_small_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdp_192_small" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_256_balanced_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdp_256_balanced" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_256_fast_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdp_256_fast" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdp_256_small_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdp_256_small" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_128_balanced_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdpg_128_balanced" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_128_fast_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdpg_128_fast" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_128_small_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdpg_128_small" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_192_balanced_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdpg_192_balanced" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_192_fast_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdpg_192_fast" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_192_small_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdpg_192_small" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_256_balanced_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdpg_256_balanced" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_256_fast_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdpg_256_fast" OFF)
+endif()
+
+if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS))
+ cmake_dependent_option(OQS_ENABLE_SIG_cross_rsdpg_256_small_avx2 "" ON "OQS_ENABLE_SIG_cross_rsdpg_256_small" OFF)
+endif()
+
##### OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ENABLE_BY_ALG_CONDITIONAL_END
##### OQS_COPY_FROM_LIBJADE_FRAGMENT_ADD_ENABLE_BY_ALG_CONDITIONAL_START
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 724402e7a..0530ff1c1 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -2,9 +2,10 @@
* @dstebila
/.circleci @baentsch
-/scripts/copy_from_upstream @baentsch @bhess
+/scripts/copy_from_upstream @baentsch @bhess @alexrow
/src/common @dstebila
/src/kem/bike @crockeea
/src/kem/frodokem @dstebila
/src/kem/kyber @jschanck @bhess
+/src/sig/cross @alexrow
/src/sig/dilithium @bhess
diff --git a/.github/workflows/unix.yml b/.github/workflows/unix.yml
index 35bb8deb6..0f5b5dbe4 100644
--- a/.github/workflows/unix.yml
+++ b/.github/workflows/unix.yml
@@ -157,10 +157,10 @@ jobs:
container: openquantumsafe/ci-ubuntu-focal-x86_64:latest
CMAKE_ARGS: -DCMAKE_C_COMPILER=gcc-7 -DOQS_DIST_BUILD=OFF -DOQS_USE_OPENSSL=OFF -DBUILD_SHARED_LIBS=ON
PYTEST_ARGS: --ignore=tests/test_namespace.py --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py
- - name: focal-clang15
+ - name: jammy-clang
runner: ubuntu-latest
- container: openquantumsafe/ci-ubuntu-focal-x86_64:latest
- CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DCMAKE_C_COMPILER=clang-15
+ container: openquantumsafe/ci-ubuntu-jammy:latest
+ CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DCMAKE_C_COMPILER=clang
PYTEST_ARGS: --ignore=tests/test_kat_all.py
- name: jammy-std-openssl3
runner: ubuntu-latest
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4d897e664..6973fbc5c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -224,6 +224,9 @@ endif()
if(OQS_ENABLE_SIG_MAYO)
set(PUBLIC_HEADERS ${PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/src/sig/mayo/sig_mayo.h)
endif()
+if(OQS_ENABLE_SIG_CROSS)
+ set(PUBLIC_HEADERS ${PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/src/sig/cross/sig_cross.h)
+endif()
##### OQS_COPY_FROM_UPSTREAM_FRAGMENT_INCLUDE_HEADERS_END
if(OQS_ENABLE_SIG_STFL_XMSS)
set(PUBLIC_HEADERS ${PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/src/sig_stfl/xmss/sig_stfl_xmss.h)
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 83d9337ca..596b30520 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -35,5 +35,8 @@ Sebastian Verschoor (University of Waterloo)
Thom Wiggers (Radboud University)
Dindyal Jeevesh Rishi (University of Mauritius / cyberstorm.mu)
Duc Tri Nguyen
+Marco Gianvecchio (Politecnico di Milano)
+Alessandro Barenghi (Politecnico di Milano)
+Gerardo Pelosi (Politecnico di Milano)
See additional contributors at https://github.com/open-quantum-safe/liboqs/graphs/contributors
diff --git a/README.md b/README.md
index db67a3115..ecc62daee 100644
--- a/README.md
+++ b/README.md
@@ -61,6 +61,7 @@ All names other than `ML-KEM` and `ML-DSA` are subject to change. `liboqs` makes
#### Signature schemes
+- **CROSS**: cross-rsdp-128-balanced, cross-rsdp-128-fast, cross-rsdp-128-small†, cross-rsdp-192-balanced, cross-rsdp-192-fast, cross-rsdp-192-small†, cross-rsdp-256-balanced†, cross-rsdp-256-fast, cross-rsdp-256-small†, cross-rsdpg-128-balanced, cross-rsdpg-128-fast, cross-rsdpg-128-small, cross-rsdpg-192-balanced, cross-rsdpg-192-fast, cross-rsdpg-192-small†, cross-rsdpg-256-balanced, cross-rsdpg-256-fast, cross-rsdpg-256-small†
- **CRYSTALS-Dilithium**: Dilithium2, Dilithium3, Dilithium5
- **Falcon**: Falcon-512, Falcon-1024, Falcon-padded-512, Falcon-padded-1024
- **MAYO**: MAYO-1, MAYO-2, MAYO-3, MAYO-5†
diff --git a/docs/algorithms/sig/cross.md b/docs/algorithms/sig/cross.md
new file mode 100644
index 000000000..91de3bb82
--- /dev/null
+++ b/docs/algorithms/sig/cross.md
@@ -0,0 +1,203 @@
+# CROSS
+
+- **Algorithm type**: Digital signature scheme.
+- **Main cryptographic assumption**: hardness of the restricted syndrome decoding problem for random linear codes on a finite field.
+- **Principal submitters**: Marco Baldi, Alessandro Barenghi, Sebastian Bitzer, Patrick Karl, Felice Manganiello, Alessio Pavoni, Gerardo Pelosi, Paolo Santini, Jonas Schupp, Freeman Slaughter, Antonia Wachter-Zeh, Violetta Weger.
+- **Auxiliary submitters**: Marco Gianvecchio.
+- **Authors' website**: https://www.cross-crypto.com/
+- **Specification version**: 1.2 + Keccak_x4 + PQClean fixes.
+- **Primary Source**:
+ - **Source**: https://github.com/rtjk/CROSS-PQClean/commit/577d7c761c684637923c8648644cf2f4d7b41954
+ - **Implementation license (SPDX-Identifier)**: CC0-1.0
+
+
+## Parameter set summary
+
+| Parameter set | Parameter set alias | Security model | Claimed NIST Level | Public key size (bytes) | Secret key size (bytes) | Signature size (bytes) |
+|:------------------------:|:----------------------|:-----------------|---------------------:|--------------------------:|--------------------------:|-------------------------:|
+| cross-rsdp-128-balanced | NA | EUF-CMA | 1 | 77 | 32 | 12912 |
+| cross-rsdp-128-fast | NA | EUF-CMA | 1 | 77 | 32 | 19152 |
+| cross-rsdp-128-small | NA | EUF-CMA | 1 | 77 | 32 | 10080 |
+| cross-rsdp-192-balanced | NA | EUF-CMA | 3 | 115 | 48 | 28222 |
+| cross-rsdp-192-fast | NA | EUF-CMA | 3 | 115 | 48 | 42682 |
+| cross-rsdp-192-small | NA | EUF-CMA | 3 | 115 | 48 | 23642 |
+| cross-rsdp-256-balanced | NA | EUF-CMA | 5 | 153 | 64 | 51056 |
+| cross-rsdp-256-fast | NA | EUF-CMA | 5 | 153 | 64 | 76298 |
+| cross-rsdp-256-small | NA | EUF-CMA | 5 | 153 | 64 | 43592 |
+| cross-rsdpg-128-balanced | NA | EUF-CMA | 1 | 54 | 32 | 9236 |
+| cross-rsdpg-128-fast | NA | EUF-CMA | 1 | 54 | 32 | 12472 |
+| cross-rsdpg-128-small | NA | EUF-CMA | 1 | 54 | 32 | 7956 |
+| cross-rsdpg-192-balanced | NA | EUF-CMA | 3 | 83 | 48 | 23380 |
+| cross-rsdpg-192-fast | NA | EUF-CMA | 3 | 83 | 48 | 27404 |
+| cross-rsdpg-192-small | NA | EUF-CMA | 3 | 83 | 48 | 18188 |
+| cross-rsdpg-256-balanced | NA | EUF-CMA | 5 | 106 | 64 | 40134 |
+| cross-rsdpg-256-fast | NA | EUF-CMA | 5 | 106 | 64 | 48938 |
+| cross-rsdpg-256-small | NA | EUF-CMA | 5 | 106 | 64 | 32742 |
+
+## cross-rsdp-128-balanced implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage?‡ |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:----------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **No**.
+
+ ‡For an explanation of what this denotes, consult the [Explanation of Terms](#explanation-of-terms) section at the end of this file.
+
+## cross-rsdp-128-fast implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdp-128-small implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | True |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | True |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdp-192-balanced implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdp-192-fast implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdp-192-small implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | True |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | True |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdp-256-balanced implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | True |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | True |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdp-256-fast implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdp-256-small implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | True |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | True |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdpg-128-balanced implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdpg-128-fast implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdpg-128-small implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdpg-192-balanced implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdpg-192-fast implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdpg-192-small implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | True |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | True |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdpg-256-balanced implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdpg-256-fast implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | False |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## cross-rsdpg-256-small implementation characteristics
+
+| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? |
+|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------|
+| [Primary Source](#primary-source) | clean | All | All | None | True | True | True |
+| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | True |
+
+Are implementations chosen based on runtime CPU feature detection? **Yes**.
+
+## Explanation of Terms
+
+- **Large Stack Usage**: Implementations identified as having such may cause failures when running in threads or in constrained environments.
\ No newline at end of file
diff --git a/docs/algorithms/sig/cross.yml b/docs/algorithms/sig/cross.yml
new file mode 100644
index 000000000..616da6602
--- /dev/null
+++ b/docs/algorithms/sig/cross.yml
@@ -0,0 +1,530 @@
+name: CROSS
+type: signature
+principal-submitters:
+- Marco Baldi
+- Alessandro Barenghi
+- Sebastian Bitzer
+- Patrick Karl
+- Felice Manganiello
+- Alessio Pavoni
+- Gerardo Pelosi
+- Paolo Santini
+- Jonas Schupp
+- Freeman Slaughter
+- Antonia Wachter-Zeh
+- Violetta Weger
+auxiliary-submitters:
+- Marco Gianvecchio
+crypto-assumption: hardness of the restricted syndrome decoding problem for random
+ linear codes on a finite field
+website: https://www.cross-crypto.com/
+nist-round: 1
+spec-version: 1.2 + Keccak_x4 + PQClean fixes
+primary-upstream:
+ source: https://github.com/rtjk/CROSS-PQClean/commit/577d7c761c684637923c8648644cf2f4d7b41954
+ spdx-license-identifier: CC0-1.0
+parameter-sets:
+- name: cross-rsdp-128-balanced
+ oqs_alg: OQS_SIG_alg_cross_rsdp_128_balanced
+ claimed-nist-level: 1
+ claimed-security: EUF-CMA
+ length-public-key: 77
+ length-secret-key: 32
+ length-signature: 12912
+ implementations-switch-on-runtime-cpu-features: false
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdp-128-fast
+ oqs_alg: OQS_SIG_alg_cross_rsdp_128_fast
+ claimed-nist-level: 1
+ claimed-security: EUF-CMA
+ length-public-key: 77
+ length-secret-key: 32
+ length-signature: 19152
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdp-128-small
+ oqs_alg: OQS_SIG_alg_cross_rsdp_128_small
+ claimed-nist-level: 1
+ claimed-security: EUF-CMA
+ length-public-key: 77
+ length-secret-key: 32
+ length-signature: 10080
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
+- name: cross-rsdp-192-balanced
+ oqs_alg: OQS_SIG_alg_cross_rsdp_192_balanced
+ claimed-nist-level: 3
+ claimed-security: EUF-CMA
+ length-public-key: 115
+ length-secret-key: 48
+ length-signature: 28222
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdp-192-fast
+ oqs_alg: OQS_SIG_alg_cross_rsdp_192_fast
+ claimed-nist-level: 3
+ claimed-security: EUF-CMA
+ length-public-key: 115
+ length-secret-key: 48
+ length-signature: 42682
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdp-192-small
+ oqs_alg: OQS_SIG_alg_cross_rsdp_192_small
+ claimed-nist-level: 3
+ claimed-security: EUF-CMA
+ length-public-key: 115
+ length-secret-key: 48
+ length-signature: 23642
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
+- name: cross-rsdp-256-balanced
+ oqs_alg: OQS_SIG_alg_cross_rsdp_256_balanced
+ claimed-nist-level: 5
+ claimed-security: EUF-CMA
+ length-public-key: 153
+ length-secret-key: 64
+ length-signature: 51056
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
+- name: cross-rsdp-256-fast
+ oqs_alg: OQS_SIG_alg_cross_rsdp_256_fast
+ claimed-nist-level: 5
+ claimed-security: EUF-CMA
+ length-public-key: 153
+ length-secret-key: 64
+ length-signature: 76298
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdp-256-small
+ oqs_alg: OQS_SIG_alg_cross_rsdp_256_small
+ claimed-nist-level: 5
+ claimed-security: EUF-CMA
+ length-public-key: 153
+ length-secret-key: 64
+ length-signature: 43592
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
+- name: cross-rsdpg-128-balanced
+ oqs_alg: OQS_SIG_alg_cross_rsdpg_128_balanced
+ claimed-nist-level: 1
+ claimed-security: EUF-CMA
+ length-public-key: 54
+ length-secret-key: 32
+ length-signature: 9236
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdpg-128-fast
+ oqs_alg: OQS_SIG_alg_cross_rsdpg_128_fast
+ claimed-nist-level: 1
+ claimed-security: EUF-CMA
+ length-public-key: 54
+ length-secret-key: 32
+ length-signature: 12472
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdpg-128-small
+ oqs_alg: OQS_SIG_alg_cross_rsdpg_128_small
+ claimed-nist-level: 1
+ claimed-security: EUF-CMA
+ length-public-key: 54
+ length-secret-key: 32
+ length-signature: 7956
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdpg-192-balanced
+ oqs_alg: OQS_SIG_alg_cross_rsdpg_192_balanced
+ claimed-nist-level: 3
+ claimed-security: EUF-CMA
+ length-public-key: 83
+ length-secret-key: 48
+ length-signature: 23380
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdpg-192-fast
+ oqs_alg: OQS_SIG_alg_cross_rsdpg_192_fast
+ claimed-nist-level: 3
+ claimed-security: EUF-CMA
+ length-public-key: 83
+ length-secret-key: 48
+ length-signature: 27404
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdpg-192-small
+ oqs_alg: OQS_SIG_alg_cross_rsdpg_192_small
+ claimed-nist-level: 3
+ claimed-security: EUF-CMA
+ length-public-key: 83
+ length-secret-key: 48
+ length-signature: 18188
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
+- name: cross-rsdpg-256-balanced
+ oqs_alg: OQS_SIG_alg_cross_rsdpg_256_balanced
+ claimed-nist-level: 5
+ claimed-security: EUF-CMA
+ length-public-key: 106
+ length-secret-key: 64
+ length-signature: 40134
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdpg-256-fast
+ oqs_alg: OQS_SIG_alg_cross_rsdpg_256_fast
+ claimed-nist-level: 5
+ claimed-security: EUF-CMA
+ length-public-key: 106
+ length-secret-key: 64
+ length-signature: 48938
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: false
+- name: cross-rsdpg-256-small
+ oqs_alg: OQS_SIG_alg_cross_rsdpg_256_small
+ claimed-nist-level: 5
+ claimed-security: EUF-CMA
+ length-public-key: 106
+ length-secret-key: 64
+ length-signature: 32742
+ implementations-switch-on-runtime-cpu-features: true
+ implementations:
+ - upstream: primary-upstream
+ upstream-id: clean
+ supported-platforms: all
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
+ - upstream: primary-upstream
+ upstream-id: avx2
+ supported-platforms:
+ - architecture: x86_64
+ required_flags:
+ - avx2
+ common-crypto:
+ - SHA3: liboqs
+ no-secret-dependent-branching-claimed: true
+ no-secret-dependent-branching-checked-by-valgrind: true
+ large-stack-usage: true
diff --git a/docs/cbom.json b/docs/cbom.json
index 2fab7718a..d3bfad1d6 100644
--- a/docs/cbom.json
+++ b/docs/cbom.json
@@ -1199,6 +1199,726 @@
"nistQuantumSecurityLevel": 2
}
},
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-128-balanced:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-128-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-128-balanced:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-128-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-128-fast:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-128-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-128-fast:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-128-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-128-small:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-128-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-128-small:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-128-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-192-balanced:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-192-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-192-balanced:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-192-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-192-fast:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-192-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-192-fast:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-192-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-192-small:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-192-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-192-small:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-192-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-256-balanced:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-256-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-256-balanced:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-256-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-256-fast:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-256-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-256-fast:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-256-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-256-small:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-256-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdp-256-small:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdp-256-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-128-balanced:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-128-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-128-balanced:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-128-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-128-fast:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-128-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-128-fast:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-128-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-128-small:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-128-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-128-small:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-128-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 1
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-192-balanced:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-192-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-192-balanced:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-192-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-192-fast:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-192-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-192-fast:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-192-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-192-small:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-192-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-192-small:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-192-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 3
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-256-balanced:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-256-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-256-balanced:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-256-balanced",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-256-fast:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-256-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-256-fast:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-256-fast",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-256-small:generic",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-256-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "generic"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
+ {
+ "type": "crypto-asset",
+ "bom-ref": "alg:cross-rsdpg-256-small:x86_64",
+ "name": "CROSS",
+ "cryptoProperties": {
+ "assetType": "algorithm",
+ "algorithmProperties": {
+ "variant": "cross-rsdpg-256-small",
+ "primitive": "signature",
+ "implementationLevel": "softwarePlainRam",
+ "cryptoFunctions": [
+ "keygen",
+ "sign",
+ "verify"
+ ],
+ "implementationPlatform": "x86_64"
+ },
+ "nistQuantumSecurityLevel": 5
+ }
+ },
{
"type": "crypto-asset",
"bom-ref": "alg:Dilithium2:generic",
@@ -2469,6 +3189,42 @@
"alg:ML-KEM-1024:x86_64",
"alg:sntrup761:generic",
"alg:sntrup761:x86_64",
+ "alg:cross-rsdp-128-balanced:generic",
+ "alg:cross-rsdp-128-balanced:x86_64",
+ "alg:cross-rsdp-128-fast:generic",
+ "alg:cross-rsdp-128-fast:x86_64",
+ "alg:cross-rsdp-128-small:generic",
+ "alg:cross-rsdp-128-small:x86_64",
+ "alg:cross-rsdp-192-balanced:generic",
+ "alg:cross-rsdp-192-balanced:x86_64",
+ "alg:cross-rsdp-192-fast:generic",
+ "alg:cross-rsdp-192-fast:x86_64",
+ "alg:cross-rsdp-192-small:generic",
+ "alg:cross-rsdp-192-small:x86_64",
+ "alg:cross-rsdp-256-balanced:generic",
+ "alg:cross-rsdp-256-balanced:x86_64",
+ "alg:cross-rsdp-256-fast:generic",
+ "alg:cross-rsdp-256-fast:x86_64",
+ "alg:cross-rsdp-256-small:generic",
+ "alg:cross-rsdp-256-small:x86_64",
+ "alg:cross-rsdpg-128-balanced:generic",
+ "alg:cross-rsdpg-128-balanced:x86_64",
+ "alg:cross-rsdpg-128-fast:generic",
+ "alg:cross-rsdpg-128-fast:x86_64",
+ "alg:cross-rsdpg-128-small:generic",
+ "alg:cross-rsdpg-128-small:x86_64",
+ "alg:cross-rsdpg-192-balanced:generic",
+ "alg:cross-rsdpg-192-balanced:x86_64",
+ "alg:cross-rsdpg-192-fast:generic",
+ "alg:cross-rsdpg-192-fast:x86_64",
+ "alg:cross-rsdpg-192-small:generic",
+ "alg:cross-rsdpg-192-small:x86_64",
+ "alg:cross-rsdpg-256-balanced:generic",
+ "alg:cross-rsdpg-256-balanced:x86_64",
+ "alg:cross-rsdpg-256-fast:generic",
+ "alg:cross-rsdpg-256-fast:x86_64",
+ "alg:cross-rsdpg-256-small:generic",
+ "alg:cross-rsdpg-256-small:x86_64",
"alg:Dilithium2:generic",
"alg:Dilithium2:x86_64",
"alg:Dilithium2:armv8-a",
@@ -2948,6 +3704,258 @@
],
"dependencyType": "uses"
},
+ {
+ "ref": "alg:cross-rsdp-128-balanced:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-128-balanced:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-128-fast:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-128-fast:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-128-small:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-128-small:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-192-balanced:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-192-balanced:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-192-fast:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-192-fast:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-192-small:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-192-small:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-256-balanced:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-256-balanced:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-256-fast:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-256-fast:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-256-small:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdp-256-small:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-128-balanced:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-128-balanced:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-128-fast:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-128-fast:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-128-small:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-128-small:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-192-balanced:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-192-balanced:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-192-fast:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-192-fast:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-192-small:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-192-small:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-256-balanced:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-256-balanced:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-256-fast:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-256-fast:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-256-small:generic",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
+ {
+ "ref": "alg:cross-rsdpg-256-small:x86_64",
+ "dependsOn": [
+ "alg:sha3"
+ ],
+ "dependencyType": "uses"
+ },
{
"ref": "alg:Dilithium2:generic",
"dependsOn": [
diff --git a/scripts/copy_from_upstream/copy_from_upstream.yml b/scripts/copy_from_upstream/copy_from_upstream.yml
index 216a99ae1..a8d70af43 100644
--- a/scripts/copy_from_upstream/copy_from_upstream.yml
+++ b/scripts/copy_from_upstream/copy_from_upstream.yml
@@ -61,6 +61,13 @@ upstreams:
sig_meta_path: 'META/{pretty_name_full}_META.yml'
sig_scheme_path: '.'
patches: [pqmayo-aes.patch, pqmayo-mem.patch]
+ -
+ name: upcross
+ git_url: https://github.com/rtjk/CROSS-PQClean.git
+ git_branch: master
+ git_commit: 577d7c761c684637923c8648644cf2f4d7b41954
+ sig_meta_path: 'generate/crypto_sign/{pqclean_scheme}/META.yml'
+ sig_scheme_path: 'generate/crypto_sign/{pqclean_scheme}'
kems:
-
name: classic_mceliece
@@ -341,3 +348,98 @@ sigs:
pqclean_scheme: mayo-5
pretty_name_full: MAYO-5
signed_msg_order: sig_then_msg
+ -
+ name: cross
+ default_implementation: clean
+ upstream_location: upcross
+ schemes:
+ -
+ scheme: "rsdp_128_balanced"
+ pqclean_scheme: cross-rsdp-128-balanced
+ pretty_name_full: cross-rsdp-128-balanced
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdp_128_fast"
+ pqclean_scheme: cross-rsdp-128-fast
+ pretty_name_full: cross-rsdp-128-fast
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdp_128_small"
+ pqclean_scheme: cross-rsdp-128-small
+ pretty_name_full: cross-rsdp-128-small
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdp_192_balanced"
+ pqclean_scheme: cross-rsdp-192-balanced
+ pretty_name_full: cross-rsdp-192-balanced
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdp_192_fast"
+ pqclean_scheme: cross-rsdp-192-fast
+ pretty_name_full: cross-rsdp-192-fast
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdp_192_small"
+ pqclean_scheme: cross-rsdp-192-small
+ pretty_name_full: cross-rsdp-192-small
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdp_256_balanced"
+ pqclean_scheme: cross-rsdp-256-balanced
+ pretty_name_full: cross-rsdp-256-balanced
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdp_256_fast"
+ pqclean_scheme: cross-rsdp-256-fast
+ pretty_name_full: cross-rsdp-256-fast
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdp_256_small"
+ pqclean_scheme: cross-rsdp-256-small
+ pretty_name_full: cross-rsdp-256-small
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdpg_128_balanced"
+ pqclean_scheme: cross-rsdpg-128-balanced
+ pretty_name_full: cross-rsdpg-128-balanced
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdpg_128_fast"
+ pqclean_scheme: cross-rsdpg-128-fast
+ pretty_name_full: cross-rsdpg-128-fast
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdpg_128_small"
+ pqclean_scheme: cross-rsdpg-128-small
+ pretty_name_full: cross-rsdpg-128-small
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdpg_192_balanced"
+ pqclean_scheme: cross-rsdpg-192-balanced
+ pretty_name_full: cross-rsdpg-192-balanced
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdpg_192_fast"
+ pqclean_scheme: cross-rsdpg-192-fast
+ pretty_name_full: cross-rsdpg-192-fast
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdpg_192_small"
+ pqclean_scheme: cross-rsdpg-192-small
+ pretty_name_full: cross-rsdpg-192-small
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdpg_256_balanced"
+ pqclean_scheme: cross-rsdpg-256-balanced
+ pretty_name_full: cross-rsdpg-256-balanced
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdpg_256_fast"
+ pqclean_scheme: cross-rsdpg-256-fast
+ pretty_name_full: cross-rsdpg-256-fast
+ signed_msg_order: msg_then_sig
+ -
+ scheme: "rsdpg_256_small"
+ pqclean_scheme: cross-rsdpg-256-small
+ pretty_name_full: cross-rsdpg-256-small
+ signed_msg_order: msg_then_sig
\ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 25a9b7408..debc9c59a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -59,6 +59,10 @@ if(OQS_ENABLE_SIG_MAYO)
add_subdirectory(sig/mayo)
set(SIG_OBJS ${SIG_OBJS} ${MAYO_OBJS})
endif()
+if(OQS_ENABLE_SIG_CROSS)
+ add_subdirectory(sig/cross)
+ set(SIG_OBJS ${SIG_OBJS} ${CROSS_OBJS})
+endif()
##### OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ALG_OBJECTS_END
if(OQS_ENABLE_SIG_STFL_XMSS)
diff --git a/src/oqsconfig.h.cmake b/src/oqsconfig.h.cmake
index 770202038..dae1babad 100644
--- a/src/oqsconfig.h.cmake
+++ b/src/oqsconfig.h.cmake
@@ -193,6 +193,44 @@
#cmakedefine OQS_ENABLE_SIG_mayo_3_avx2 1
#cmakedefine OQS_ENABLE_SIG_mayo_5 1
#cmakedefine OQS_ENABLE_SIG_mayo_5_avx2 1
+
+#cmakedefine OQS_ENABLE_SIG_CROSS 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_128_balanced 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_128_balanced_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_128_fast 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_128_fast_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_128_small 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_128_small_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_192_balanced 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_192_balanced_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_192_fast 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_192_fast_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_192_small 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_192_small_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_256_balanced 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_256_balanced_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_256_fast 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_256_fast_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_256_small 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdp_256_small_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_128_balanced 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_128_balanced_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_128_fast 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_128_fast_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_128_small 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_128_small_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_192_balanced 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_192_balanced_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_192_fast 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_192_fast_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_192_small 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_192_small_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_256_balanced 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_256_balanced_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_256_fast 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_256_fast_avx2 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_256_small 1
+#cmakedefine OQS_ENABLE_SIG_cross_rsdpg_256_small_avx2 1
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ALG_ENABLE_DEFINES_END
///// OQS_COPY_FROM_LIBJADE_FRAGMENT_ADD_ALG_ENABLE_DEFINES_START
diff --git a/src/sig/cross/CMakeLists.txt b/src/sig/cross/CMakeLists.txt
new file mode 100644
index 000000000..c05236381
--- /dev/null
+++ b/src/sig/cross/CMakeLists.txt
@@ -0,0 +1,278 @@
+# SPDX-License-Identifier: MIT
+
+# This file was generated by
+# scripts/copy_from_upstream/copy_from_upstream.py
+
+set(_CROSS_OBJS "")
+
+if(OQS_ENABLE_SIG_cross_rsdp_128_balanced)
+ add_library(cross_rsdp_128_balanced_clean OBJECT sig_cross_rsdp_128_balanced.c upcross_cross-rsdp-128-balanced_clean/CROSS.c upcross_cross-rsdp-128-balanced_clean/csprng_hash.c upcross_cross-rsdp-128-balanced_clean/merkle.c upcross_cross-rsdp-128-balanced_clean/pack_unpack.c upcross_cross-rsdp-128-balanced_clean/seedtree.c upcross_cross-rsdp-128-balanced_clean/sign.c)
+ target_include_directories(cross_rsdp_128_balanced_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-128-balanced_clean)
+ target_include_directories(cross_rsdp_128_balanced_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_128_balanced_avx2)
+ add_library(cross_rsdp_128_balanced_avx2 OBJECT upcross_cross-rsdp-128-balanced_avx2/CROSS.c upcross_cross-rsdp-128-balanced_avx2/csprng_hash.c upcross_cross-rsdp-128-balanced_avx2/merkle.c upcross_cross-rsdp-128-balanced_avx2/pack_unpack.c upcross_cross-rsdp-128-balanced_avx2/seedtree.c upcross_cross-rsdp-128-balanced_avx2/sign.c)
+ target_include_directories(cross_rsdp_128_balanced_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-128-balanced_avx2)
+ target_include_directories(cross_rsdp_128_balanced_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdp_128_balanced_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_128_fast)
+ add_library(cross_rsdp_128_fast_clean OBJECT sig_cross_rsdp_128_fast.c upcross_cross-rsdp-128-fast_clean/CROSS.c upcross_cross-rsdp-128-fast_clean/csprng_hash.c upcross_cross-rsdp-128-fast_clean/merkle.c upcross_cross-rsdp-128-fast_clean/pack_unpack.c upcross_cross-rsdp-128-fast_clean/seedtree.c upcross_cross-rsdp-128-fast_clean/sign.c)
+ target_include_directories(cross_rsdp_128_fast_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-128-fast_clean)
+ target_include_directories(cross_rsdp_128_fast_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_128_fast_avx2)
+ add_library(cross_rsdp_128_fast_avx2 OBJECT upcross_cross-rsdp-128-fast_avx2/CROSS.c upcross_cross-rsdp-128-fast_avx2/csprng_hash.c upcross_cross-rsdp-128-fast_avx2/merkle.c upcross_cross-rsdp-128-fast_avx2/pack_unpack.c upcross_cross-rsdp-128-fast_avx2/seedtree.c upcross_cross-rsdp-128-fast_avx2/sign.c)
+ target_include_directories(cross_rsdp_128_fast_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-128-fast_avx2)
+ target_include_directories(cross_rsdp_128_fast_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdp_128_fast_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_128_small)
+ add_library(cross_rsdp_128_small_clean OBJECT sig_cross_rsdp_128_small.c upcross_cross-rsdp-128-small_clean/CROSS.c upcross_cross-rsdp-128-small_clean/csprng_hash.c upcross_cross-rsdp-128-small_clean/merkle.c upcross_cross-rsdp-128-small_clean/pack_unpack.c upcross_cross-rsdp-128-small_clean/seedtree.c upcross_cross-rsdp-128-small_clean/sign.c)
+ target_include_directories(cross_rsdp_128_small_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-128-small_clean)
+ target_include_directories(cross_rsdp_128_small_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_128_small_avx2)
+ add_library(cross_rsdp_128_small_avx2 OBJECT upcross_cross-rsdp-128-small_avx2/CROSS.c upcross_cross-rsdp-128-small_avx2/csprng_hash.c upcross_cross-rsdp-128-small_avx2/merkle.c upcross_cross-rsdp-128-small_avx2/pack_unpack.c upcross_cross-rsdp-128-small_avx2/seedtree.c upcross_cross-rsdp-128-small_avx2/sign.c)
+ target_include_directories(cross_rsdp_128_small_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-128-small_avx2)
+ target_include_directories(cross_rsdp_128_small_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdp_128_small_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_192_balanced)
+ add_library(cross_rsdp_192_balanced_clean OBJECT sig_cross_rsdp_192_balanced.c upcross_cross-rsdp-192-balanced_clean/CROSS.c upcross_cross-rsdp-192-balanced_clean/csprng_hash.c upcross_cross-rsdp-192-balanced_clean/merkle.c upcross_cross-rsdp-192-balanced_clean/pack_unpack.c upcross_cross-rsdp-192-balanced_clean/seedtree.c upcross_cross-rsdp-192-balanced_clean/sign.c)
+ target_include_directories(cross_rsdp_192_balanced_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-192-balanced_clean)
+ target_include_directories(cross_rsdp_192_balanced_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_192_balanced_avx2)
+ add_library(cross_rsdp_192_balanced_avx2 OBJECT upcross_cross-rsdp-192-balanced_avx2/CROSS.c upcross_cross-rsdp-192-balanced_avx2/csprng_hash.c upcross_cross-rsdp-192-balanced_avx2/merkle.c upcross_cross-rsdp-192-balanced_avx2/pack_unpack.c upcross_cross-rsdp-192-balanced_avx2/seedtree.c upcross_cross-rsdp-192-balanced_avx2/sign.c)
+ target_include_directories(cross_rsdp_192_balanced_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-192-balanced_avx2)
+ target_include_directories(cross_rsdp_192_balanced_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdp_192_balanced_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_192_fast)
+ add_library(cross_rsdp_192_fast_clean OBJECT sig_cross_rsdp_192_fast.c upcross_cross-rsdp-192-fast_clean/CROSS.c upcross_cross-rsdp-192-fast_clean/csprng_hash.c upcross_cross-rsdp-192-fast_clean/merkle.c upcross_cross-rsdp-192-fast_clean/pack_unpack.c upcross_cross-rsdp-192-fast_clean/seedtree.c upcross_cross-rsdp-192-fast_clean/sign.c)
+ target_include_directories(cross_rsdp_192_fast_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-192-fast_clean)
+ target_include_directories(cross_rsdp_192_fast_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_192_fast_avx2)
+ add_library(cross_rsdp_192_fast_avx2 OBJECT upcross_cross-rsdp-192-fast_avx2/CROSS.c upcross_cross-rsdp-192-fast_avx2/csprng_hash.c upcross_cross-rsdp-192-fast_avx2/merkle.c upcross_cross-rsdp-192-fast_avx2/pack_unpack.c upcross_cross-rsdp-192-fast_avx2/seedtree.c upcross_cross-rsdp-192-fast_avx2/sign.c)
+ target_include_directories(cross_rsdp_192_fast_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-192-fast_avx2)
+ target_include_directories(cross_rsdp_192_fast_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdp_192_fast_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_192_small)
+ add_library(cross_rsdp_192_small_clean OBJECT sig_cross_rsdp_192_small.c upcross_cross-rsdp-192-small_clean/CROSS.c upcross_cross-rsdp-192-small_clean/csprng_hash.c upcross_cross-rsdp-192-small_clean/merkle.c upcross_cross-rsdp-192-small_clean/pack_unpack.c upcross_cross-rsdp-192-small_clean/seedtree.c upcross_cross-rsdp-192-small_clean/sign.c)
+ target_include_directories(cross_rsdp_192_small_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-192-small_clean)
+ target_include_directories(cross_rsdp_192_small_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_192_small_avx2)
+ add_library(cross_rsdp_192_small_avx2 OBJECT upcross_cross-rsdp-192-small_avx2/CROSS.c upcross_cross-rsdp-192-small_avx2/csprng_hash.c upcross_cross-rsdp-192-small_avx2/merkle.c upcross_cross-rsdp-192-small_avx2/pack_unpack.c upcross_cross-rsdp-192-small_avx2/seedtree.c upcross_cross-rsdp-192-small_avx2/sign.c)
+ target_include_directories(cross_rsdp_192_small_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-192-small_avx2)
+ target_include_directories(cross_rsdp_192_small_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdp_192_small_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_256_balanced)
+ add_library(cross_rsdp_256_balanced_clean OBJECT sig_cross_rsdp_256_balanced.c upcross_cross-rsdp-256-balanced_clean/CROSS.c upcross_cross-rsdp-256-balanced_clean/csprng_hash.c upcross_cross-rsdp-256-balanced_clean/merkle.c upcross_cross-rsdp-256-balanced_clean/pack_unpack.c upcross_cross-rsdp-256-balanced_clean/seedtree.c upcross_cross-rsdp-256-balanced_clean/sign.c)
+ target_include_directories(cross_rsdp_256_balanced_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-256-balanced_clean)
+ target_include_directories(cross_rsdp_256_balanced_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_256_balanced_avx2)
+ add_library(cross_rsdp_256_balanced_avx2 OBJECT upcross_cross-rsdp-256-balanced_avx2/CROSS.c upcross_cross-rsdp-256-balanced_avx2/csprng_hash.c upcross_cross-rsdp-256-balanced_avx2/merkle.c upcross_cross-rsdp-256-balanced_avx2/pack_unpack.c upcross_cross-rsdp-256-balanced_avx2/seedtree.c upcross_cross-rsdp-256-balanced_avx2/sign.c)
+ target_include_directories(cross_rsdp_256_balanced_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-256-balanced_avx2)
+ target_include_directories(cross_rsdp_256_balanced_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdp_256_balanced_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_256_fast)
+ add_library(cross_rsdp_256_fast_clean OBJECT sig_cross_rsdp_256_fast.c upcross_cross-rsdp-256-fast_clean/CROSS.c upcross_cross-rsdp-256-fast_clean/csprng_hash.c upcross_cross-rsdp-256-fast_clean/merkle.c upcross_cross-rsdp-256-fast_clean/pack_unpack.c upcross_cross-rsdp-256-fast_clean/seedtree.c upcross_cross-rsdp-256-fast_clean/sign.c)
+ target_include_directories(cross_rsdp_256_fast_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-256-fast_clean)
+ target_include_directories(cross_rsdp_256_fast_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_256_fast_avx2)
+ add_library(cross_rsdp_256_fast_avx2 OBJECT upcross_cross-rsdp-256-fast_avx2/CROSS.c upcross_cross-rsdp-256-fast_avx2/csprng_hash.c upcross_cross-rsdp-256-fast_avx2/merkle.c upcross_cross-rsdp-256-fast_avx2/pack_unpack.c upcross_cross-rsdp-256-fast_avx2/seedtree.c upcross_cross-rsdp-256-fast_avx2/sign.c)
+ target_include_directories(cross_rsdp_256_fast_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-256-fast_avx2)
+ target_include_directories(cross_rsdp_256_fast_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdp_256_fast_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_256_small)
+ add_library(cross_rsdp_256_small_clean OBJECT sig_cross_rsdp_256_small.c upcross_cross-rsdp-256-small_clean/CROSS.c upcross_cross-rsdp-256-small_clean/csprng_hash.c upcross_cross-rsdp-256-small_clean/merkle.c upcross_cross-rsdp-256-small_clean/pack_unpack.c upcross_cross-rsdp-256-small_clean/seedtree.c upcross_cross-rsdp-256-small_clean/sign.c)
+ target_include_directories(cross_rsdp_256_small_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-256-small_clean)
+ target_include_directories(cross_rsdp_256_small_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdp_256_small_avx2)
+ add_library(cross_rsdp_256_small_avx2 OBJECT upcross_cross-rsdp-256-small_avx2/CROSS.c upcross_cross-rsdp-256-small_avx2/csprng_hash.c upcross_cross-rsdp-256-small_avx2/merkle.c upcross_cross-rsdp-256-small_avx2/pack_unpack.c upcross_cross-rsdp-256-small_avx2/seedtree.c upcross_cross-rsdp-256-small_avx2/sign.c)
+ target_include_directories(cross_rsdp_256_small_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdp-256-small_avx2)
+ target_include_directories(cross_rsdp_256_small_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdp_256_small_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_128_balanced)
+ add_library(cross_rsdpg_128_balanced_clean OBJECT sig_cross_rsdpg_128_balanced.c upcross_cross-rsdpg-128-balanced_clean/CROSS.c upcross_cross-rsdpg-128-balanced_clean/csprng_hash.c upcross_cross-rsdpg-128-balanced_clean/merkle.c upcross_cross-rsdpg-128-balanced_clean/pack_unpack.c upcross_cross-rsdpg-128-balanced_clean/seedtree.c upcross_cross-rsdpg-128-balanced_clean/sign.c)
+ target_include_directories(cross_rsdpg_128_balanced_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-128-balanced_clean)
+ target_include_directories(cross_rsdpg_128_balanced_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_128_balanced_avx2)
+ add_library(cross_rsdpg_128_balanced_avx2 OBJECT upcross_cross-rsdpg-128-balanced_avx2/CROSS.c upcross_cross-rsdpg-128-balanced_avx2/csprng_hash.c upcross_cross-rsdpg-128-balanced_avx2/merkle.c upcross_cross-rsdpg-128-balanced_avx2/pack_unpack.c upcross_cross-rsdpg-128-balanced_avx2/seedtree.c upcross_cross-rsdpg-128-balanced_avx2/sign.c)
+ target_include_directories(cross_rsdpg_128_balanced_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-128-balanced_avx2)
+ target_include_directories(cross_rsdpg_128_balanced_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdpg_128_balanced_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_128_fast)
+ add_library(cross_rsdpg_128_fast_clean OBJECT sig_cross_rsdpg_128_fast.c upcross_cross-rsdpg-128-fast_clean/CROSS.c upcross_cross-rsdpg-128-fast_clean/csprng_hash.c upcross_cross-rsdpg-128-fast_clean/merkle.c upcross_cross-rsdpg-128-fast_clean/pack_unpack.c upcross_cross-rsdpg-128-fast_clean/seedtree.c upcross_cross-rsdpg-128-fast_clean/sign.c)
+ target_include_directories(cross_rsdpg_128_fast_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-128-fast_clean)
+ target_include_directories(cross_rsdpg_128_fast_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_128_fast_avx2)
+ add_library(cross_rsdpg_128_fast_avx2 OBJECT upcross_cross-rsdpg-128-fast_avx2/CROSS.c upcross_cross-rsdpg-128-fast_avx2/csprng_hash.c upcross_cross-rsdpg-128-fast_avx2/merkle.c upcross_cross-rsdpg-128-fast_avx2/pack_unpack.c upcross_cross-rsdpg-128-fast_avx2/seedtree.c upcross_cross-rsdpg-128-fast_avx2/sign.c)
+ target_include_directories(cross_rsdpg_128_fast_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-128-fast_avx2)
+ target_include_directories(cross_rsdpg_128_fast_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdpg_128_fast_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_128_small)
+ add_library(cross_rsdpg_128_small_clean OBJECT sig_cross_rsdpg_128_small.c upcross_cross-rsdpg-128-small_clean/CROSS.c upcross_cross-rsdpg-128-small_clean/csprng_hash.c upcross_cross-rsdpg-128-small_clean/merkle.c upcross_cross-rsdpg-128-small_clean/pack_unpack.c upcross_cross-rsdpg-128-small_clean/seedtree.c upcross_cross-rsdpg-128-small_clean/sign.c)
+ target_include_directories(cross_rsdpg_128_small_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-128-small_clean)
+ target_include_directories(cross_rsdpg_128_small_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_128_small_avx2)
+ add_library(cross_rsdpg_128_small_avx2 OBJECT upcross_cross-rsdpg-128-small_avx2/CROSS.c upcross_cross-rsdpg-128-small_avx2/csprng_hash.c upcross_cross-rsdpg-128-small_avx2/merkle.c upcross_cross-rsdpg-128-small_avx2/pack_unpack.c upcross_cross-rsdpg-128-small_avx2/seedtree.c upcross_cross-rsdpg-128-small_avx2/sign.c)
+ target_include_directories(cross_rsdpg_128_small_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-128-small_avx2)
+ target_include_directories(cross_rsdpg_128_small_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdpg_128_small_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_192_balanced)
+ add_library(cross_rsdpg_192_balanced_clean OBJECT sig_cross_rsdpg_192_balanced.c upcross_cross-rsdpg-192-balanced_clean/CROSS.c upcross_cross-rsdpg-192-balanced_clean/csprng_hash.c upcross_cross-rsdpg-192-balanced_clean/merkle.c upcross_cross-rsdpg-192-balanced_clean/pack_unpack.c upcross_cross-rsdpg-192-balanced_clean/seedtree.c upcross_cross-rsdpg-192-balanced_clean/sign.c)
+ target_include_directories(cross_rsdpg_192_balanced_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-192-balanced_clean)
+ target_include_directories(cross_rsdpg_192_balanced_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_192_balanced_avx2)
+ add_library(cross_rsdpg_192_balanced_avx2 OBJECT upcross_cross-rsdpg-192-balanced_avx2/CROSS.c upcross_cross-rsdpg-192-balanced_avx2/csprng_hash.c upcross_cross-rsdpg-192-balanced_avx2/merkle.c upcross_cross-rsdpg-192-balanced_avx2/pack_unpack.c upcross_cross-rsdpg-192-balanced_avx2/seedtree.c upcross_cross-rsdpg-192-balanced_avx2/sign.c)
+ target_include_directories(cross_rsdpg_192_balanced_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-192-balanced_avx2)
+ target_include_directories(cross_rsdpg_192_balanced_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdpg_192_balanced_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_192_fast)
+ add_library(cross_rsdpg_192_fast_clean OBJECT sig_cross_rsdpg_192_fast.c upcross_cross-rsdpg-192-fast_clean/CROSS.c upcross_cross-rsdpg-192-fast_clean/csprng_hash.c upcross_cross-rsdpg-192-fast_clean/merkle.c upcross_cross-rsdpg-192-fast_clean/pack_unpack.c upcross_cross-rsdpg-192-fast_clean/seedtree.c upcross_cross-rsdpg-192-fast_clean/sign.c)
+ target_include_directories(cross_rsdpg_192_fast_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-192-fast_clean)
+ target_include_directories(cross_rsdpg_192_fast_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_192_fast_avx2)
+ add_library(cross_rsdpg_192_fast_avx2 OBJECT upcross_cross-rsdpg-192-fast_avx2/CROSS.c upcross_cross-rsdpg-192-fast_avx2/csprng_hash.c upcross_cross-rsdpg-192-fast_avx2/merkle.c upcross_cross-rsdpg-192-fast_avx2/pack_unpack.c upcross_cross-rsdpg-192-fast_avx2/seedtree.c upcross_cross-rsdpg-192-fast_avx2/sign.c)
+ target_include_directories(cross_rsdpg_192_fast_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-192-fast_avx2)
+ target_include_directories(cross_rsdpg_192_fast_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdpg_192_fast_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_192_small)
+ add_library(cross_rsdpg_192_small_clean OBJECT sig_cross_rsdpg_192_small.c upcross_cross-rsdpg-192-small_clean/CROSS.c upcross_cross-rsdpg-192-small_clean/csprng_hash.c upcross_cross-rsdpg-192-small_clean/merkle.c upcross_cross-rsdpg-192-small_clean/pack_unpack.c upcross_cross-rsdpg-192-small_clean/seedtree.c upcross_cross-rsdpg-192-small_clean/sign.c)
+ target_include_directories(cross_rsdpg_192_small_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-192-small_clean)
+ target_include_directories(cross_rsdpg_192_small_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_192_small_avx2)
+ add_library(cross_rsdpg_192_small_avx2 OBJECT upcross_cross-rsdpg-192-small_avx2/CROSS.c upcross_cross-rsdpg-192-small_avx2/csprng_hash.c upcross_cross-rsdpg-192-small_avx2/merkle.c upcross_cross-rsdpg-192-small_avx2/pack_unpack.c upcross_cross-rsdpg-192-small_avx2/seedtree.c upcross_cross-rsdpg-192-small_avx2/sign.c)
+ target_include_directories(cross_rsdpg_192_small_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-192-small_avx2)
+ target_include_directories(cross_rsdpg_192_small_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdpg_192_small_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_256_balanced)
+ add_library(cross_rsdpg_256_balanced_clean OBJECT sig_cross_rsdpg_256_balanced.c upcross_cross-rsdpg-256-balanced_clean/CROSS.c upcross_cross-rsdpg-256-balanced_clean/csprng_hash.c upcross_cross-rsdpg-256-balanced_clean/merkle.c upcross_cross-rsdpg-256-balanced_clean/pack_unpack.c upcross_cross-rsdpg-256-balanced_clean/seedtree.c upcross_cross-rsdpg-256-balanced_clean/sign.c)
+ target_include_directories(cross_rsdpg_256_balanced_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-256-balanced_clean)
+ target_include_directories(cross_rsdpg_256_balanced_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_256_balanced_avx2)
+ add_library(cross_rsdpg_256_balanced_avx2 OBJECT upcross_cross-rsdpg-256-balanced_avx2/CROSS.c upcross_cross-rsdpg-256-balanced_avx2/csprng_hash.c upcross_cross-rsdpg-256-balanced_avx2/merkle.c upcross_cross-rsdpg-256-balanced_avx2/pack_unpack.c upcross_cross-rsdpg-256-balanced_avx2/seedtree.c upcross_cross-rsdpg-256-balanced_avx2/sign.c)
+ target_include_directories(cross_rsdpg_256_balanced_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-256-balanced_avx2)
+ target_include_directories(cross_rsdpg_256_balanced_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdpg_256_balanced_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_256_fast)
+ add_library(cross_rsdpg_256_fast_clean OBJECT sig_cross_rsdpg_256_fast.c upcross_cross-rsdpg-256-fast_clean/CROSS.c upcross_cross-rsdpg-256-fast_clean/csprng_hash.c upcross_cross-rsdpg-256-fast_clean/merkle.c upcross_cross-rsdpg-256-fast_clean/pack_unpack.c upcross_cross-rsdpg-256-fast_clean/seedtree.c upcross_cross-rsdpg-256-fast_clean/sign.c)
+ target_include_directories(cross_rsdpg_256_fast_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-256-fast_clean)
+ target_include_directories(cross_rsdpg_256_fast_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_256_fast_avx2)
+ add_library(cross_rsdpg_256_fast_avx2 OBJECT upcross_cross-rsdpg-256-fast_avx2/CROSS.c upcross_cross-rsdpg-256-fast_avx2/csprng_hash.c upcross_cross-rsdpg-256-fast_avx2/merkle.c upcross_cross-rsdpg-256-fast_avx2/pack_unpack.c upcross_cross-rsdpg-256-fast_avx2/seedtree.c upcross_cross-rsdpg-256-fast_avx2/sign.c)
+ target_include_directories(cross_rsdpg_256_fast_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-256-fast_avx2)
+ target_include_directories(cross_rsdpg_256_fast_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdpg_256_fast_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_256_small)
+ add_library(cross_rsdpg_256_small_clean OBJECT sig_cross_rsdpg_256_small.c upcross_cross-rsdpg-256-small_clean/CROSS.c upcross_cross-rsdpg-256-small_clean/csprng_hash.c upcross_cross-rsdpg-256-small_clean/merkle.c upcross_cross-rsdpg-256-small_clean/pack_unpack.c upcross_cross-rsdpg-256-small_clean/seedtree.c upcross_cross-rsdpg-256-small_clean/sign.c)
+ target_include_directories(cross_rsdpg_256_small_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-256-small_clean)
+ target_include_directories(cross_rsdpg_256_small_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+if(OQS_ENABLE_SIG_cross_rsdpg_256_small_avx2)
+ add_library(cross_rsdpg_256_small_avx2 OBJECT upcross_cross-rsdpg-256-small_avx2/CROSS.c upcross_cross-rsdpg-256-small_avx2/csprng_hash.c upcross_cross-rsdpg-256-small_avx2/merkle.c upcross_cross-rsdpg-256-small_avx2/pack_unpack.c upcross_cross-rsdpg-256-small_avx2/seedtree.c upcross_cross-rsdpg-256-small_avx2/sign.c)
+ target_include_directories(cross_rsdpg_256_small_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/upcross_cross-rsdpg-256-small_avx2)
+ target_include_directories(cross_rsdpg_256_small_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims)
+ target_compile_options(cross_rsdpg_256_small_avx2 PRIVATE -mavx2)
+ set(_CROSS_OBJS ${_CROSS_OBJS} $)
+endif()
+
+set(CROSS_OBJS ${_CROSS_OBJS} PARENT_SCOPE)
diff --git a/src/sig/cross/sig_cross.h b/src/sig/cross/sig_cross.h
new file mode 100644
index 000000000..641002643
--- /dev/null
+++ b/src/sig/cross/sig_cross.h
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: MIT
+
+#ifndef OQS_SIG_CROSS_H
+#define OQS_SIG_CROSS_H
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_balanced)
+#define OQS_SIG_cross_rsdp_128_balanced_length_public_key 77
+#define OQS_SIG_cross_rsdp_128_balanced_length_secret_key 32
+#define OQS_SIG_cross_rsdp_128_balanced_length_signature 12912
+
+OQS_SIG *OQS_SIG_cross_rsdp_128_balanced_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_balanced_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_fast)
+#define OQS_SIG_cross_rsdp_128_fast_length_public_key 77
+#define OQS_SIG_cross_rsdp_128_fast_length_secret_key 32
+#define OQS_SIG_cross_rsdp_128_fast_length_signature 19152
+
+OQS_SIG *OQS_SIG_cross_rsdp_128_fast_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_fast_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_small)
+#define OQS_SIG_cross_rsdp_128_small_length_public_key 77
+#define OQS_SIG_cross_rsdp_128_small_length_secret_key 32
+#define OQS_SIG_cross_rsdp_128_small_length_signature 10080
+
+OQS_SIG *OQS_SIG_cross_rsdp_128_small_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_small_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_balanced)
+#define OQS_SIG_cross_rsdp_192_balanced_length_public_key 115
+#define OQS_SIG_cross_rsdp_192_balanced_length_secret_key 48
+#define OQS_SIG_cross_rsdp_192_balanced_length_signature 28222
+
+OQS_SIG *OQS_SIG_cross_rsdp_192_balanced_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_balanced_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_fast)
+#define OQS_SIG_cross_rsdp_192_fast_length_public_key 115
+#define OQS_SIG_cross_rsdp_192_fast_length_secret_key 48
+#define OQS_SIG_cross_rsdp_192_fast_length_signature 42682
+
+OQS_SIG *OQS_SIG_cross_rsdp_192_fast_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_fast_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_small)
+#define OQS_SIG_cross_rsdp_192_small_length_public_key 115
+#define OQS_SIG_cross_rsdp_192_small_length_secret_key 48
+#define OQS_SIG_cross_rsdp_192_small_length_signature 23642
+
+OQS_SIG *OQS_SIG_cross_rsdp_192_small_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_small_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_balanced)
+#define OQS_SIG_cross_rsdp_256_balanced_length_public_key 153
+#define OQS_SIG_cross_rsdp_256_balanced_length_secret_key 64
+#define OQS_SIG_cross_rsdp_256_balanced_length_signature 51056
+
+OQS_SIG *OQS_SIG_cross_rsdp_256_balanced_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_balanced_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_fast)
+#define OQS_SIG_cross_rsdp_256_fast_length_public_key 153
+#define OQS_SIG_cross_rsdp_256_fast_length_secret_key 64
+#define OQS_SIG_cross_rsdp_256_fast_length_signature 76298
+
+OQS_SIG *OQS_SIG_cross_rsdp_256_fast_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_fast_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_small)
+#define OQS_SIG_cross_rsdp_256_small_length_public_key 153
+#define OQS_SIG_cross_rsdp_256_small_length_secret_key 64
+#define OQS_SIG_cross_rsdp_256_small_length_signature 43592
+
+OQS_SIG *OQS_SIG_cross_rsdp_256_small_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_small_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_balanced)
+#define OQS_SIG_cross_rsdpg_128_balanced_length_public_key 54
+#define OQS_SIG_cross_rsdpg_128_balanced_length_secret_key 32
+#define OQS_SIG_cross_rsdpg_128_balanced_length_signature 9236
+
+OQS_SIG *OQS_SIG_cross_rsdpg_128_balanced_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_balanced_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_fast)
+#define OQS_SIG_cross_rsdpg_128_fast_length_public_key 54
+#define OQS_SIG_cross_rsdpg_128_fast_length_secret_key 32
+#define OQS_SIG_cross_rsdpg_128_fast_length_signature 12472
+
+OQS_SIG *OQS_SIG_cross_rsdpg_128_fast_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_fast_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_small)
+#define OQS_SIG_cross_rsdpg_128_small_length_public_key 54
+#define OQS_SIG_cross_rsdpg_128_small_length_secret_key 32
+#define OQS_SIG_cross_rsdpg_128_small_length_signature 7956
+
+OQS_SIG *OQS_SIG_cross_rsdpg_128_small_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_small_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_balanced)
+#define OQS_SIG_cross_rsdpg_192_balanced_length_public_key 83
+#define OQS_SIG_cross_rsdpg_192_balanced_length_secret_key 48
+#define OQS_SIG_cross_rsdpg_192_balanced_length_signature 23380
+
+OQS_SIG *OQS_SIG_cross_rsdpg_192_balanced_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_balanced_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_fast)
+#define OQS_SIG_cross_rsdpg_192_fast_length_public_key 83
+#define OQS_SIG_cross_rsdpg_192_fast_length_secret_key 48
+#define OQS_SIG_cross_rsdpg_192_fast_length_signature 27404
+
+OQS_SIG *OQS_SIG_cross_rsdpg_192_fast_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_fast_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_small)
+#define OQS_SIG_cross_rsdpg_192_small_length_public_key 83
+#define OQS_SIG_cross_rsdpg_192_small_length_secret_key 48
+#define OQS_SIG_cross_rsdpg_192_small_length_signature 18188
+
+OQS_SIG *OQS_SIG_cross_rsdpg_192_small_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_small_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_balanced)
+#define OQS_SIG_cross_rsdpg_256_balanced_length_public_key 106
+#define OQS_SIG_cross_rsdpg_256_balanced_length_secret_key 64
+#define OQS_SIG_cross_rsdpg_256_balanced_length_signature 40134
+
+OQS_SIG *OQS_SIG_cross_rsdpg_256_balanced_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_balanced_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_fast)
+#define OQS_SIG_cross_rsdpg_256_fast_length_public_key 106
+#define OQS_SIG_cross_rsdpg_256_fast_length_secret_key 64
+#define OQS_SIG_cross_rsdpg_256_fast_length_signature 48938
+
+OQS_SIG *OQS_SIG_cross_rsdpg_256_fast_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_fast_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_small)
+#define OQS_SIG_cross_rsdpg_256_small_length_public_key 106
+#define OQS_SIG_cross_rsdpg_256_small_length_secret_key 64
+#define OQS_SIG_cross_rsdpg_256_small_length_signature 32742
+
+OQS_SIG *OQS_SIG_cross_rsdpg_256_small_new(void);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_small_keypair(uint8_t *public_key, uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
+#endif
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdp_128_balanced.c b/src/sig/cross/sig_cross_rsdp_128_balanced.c
new file mode 100644
index 000000000..046000423
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdp_128_balanced.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_balanced)
+
+OQS_SIG *OQS_SIG_cross_rsdp_128_balanced_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdp_128_balanced;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 1;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdp_128_balanced_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdp_128_balanced_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdp_128_balanced_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdp_128_balanced_keypair;
+ sig->sign = OQS_SIG_cross_rsdp_128_balanced_sign;
+ sig->verify = OQS_SIG_cross_rsdp_128_balanced_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_balanced_avx2)
+extern int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_balanced_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdp_128_fast.c b/src/sig/cross/sig_cross_rsdp_128_fast.c
new file mode 100644
index 000000000..5ad9f0ae3
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdp_128_fast.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_fast)
+
+OQS_SIG *OQS_SIG_cross_rsdp_128_fast_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdp_128_fast;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 1;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdp_128_fast_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdp_128_fast_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdp_128_fast_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdp_128_fast_keypair;
+ sig->sign = OQS_SIG_cross_rsdp_128_fast_sign;
+ sig->verify = OQS_SIG_cross_rsdp_128_fast_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_fast_avx2)
+extern int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_fast_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdp_128_small.c b/src/sig/cross/sig_cross_rsdp_128_small.c
new file mode 100644
index 000000000..24fb6f6cb
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdp_128_small.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_small)
+
+OQS_SIG *OQS_SIG_cross_rsdp_128_small_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdp_128_small;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 1;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdp_128_small_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdp_128_small_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdp_128_small_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdp_128_small_keypair;
+ sig->sign = OQS_SIG_cross_rsdp_128_small_sign;
+ sig->verify = OQS_SIG_cross_rsdp_128_small_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDP128SMALL_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128SMALL_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128SMALL_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_small_avx2)
+extern int PQCLEAN_CROSSRSDP128SMALL_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128SMALL_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP128SMALL_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_small_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128SMALL_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128SMALL_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_128_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_128_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128SMALL_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP128SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdp_192_balanced.c b/src/sig/cross/sig_cross_rsdp_192_balanced.c
new file mode 100644
index 000000000..f4cc950cb
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdp_192_balanced.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_balanced)
+
+OQS_SIG *OQS_SIG_cross_rsdp_192_balanced_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdp_192_balanced;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 3;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdp_192_balanced_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdp_192_balanced_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdp_192_balanced_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdp_192_balanced_keypair;
+ sig->sign = OQS_SIG_cross_rsdp_192_balanced_sign;
+ sig->verify = OQS_SIG_cross_rsdp_192_balanced_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDP192BALANCED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192BALANCED_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192BALANCED_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_balanced_avx2)
+extern int PQCLEAN_CROSSRSDP192BALANCED_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192BALANCED_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192BALANCED_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_balanced_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192BALANCED_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192BALANCED_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192BALANCED_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdp_192_fast.c b/src/sig/cross/sig_cross_rsdp_192_fast.c
new file mode 100644
index 000000000..8bed778f6
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdp_192_fast.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_fast)
+
+OQS_SIG *OQS_SIG_cross_rsdp_192_fast_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdp_192_fast;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 3;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdp_192_fast_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdp_192_fast_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdp_192_fast_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdp_192_fast_keypair;
+ sig->sign = OQS_SIG_cross_rsdp_192_fast_sign;
+ sig->verify = OQS_SIG_cross_rsdp_192_fast_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDP192FAST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192FAST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192FAST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_fast_avx2)
+extern int PQCLEAN_CROSSRSDP192FAST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192FAST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192FAST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_fast_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192FAST_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192FAST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192FAST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdp_192_small.c b/src/sig/cross/sig_cross_rsdp_192_small.c
new file mode 100644
index 000000000..53864a866
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdp_192_small.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_small)
+
+OQS_SIG *OQS_SIG_cross_rsdp_192_small_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdp_192_small;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 3;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdp_192_small_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdp_192_small_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdp_192_small_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdp_192_small_keypair;
+ sig->sign = OQS_SIG_cross_rsdp_192_small_sign;
+ sig->verify = OQS_SIG_cross_rsdp_192_small_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDP192SMALL_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192SMALL_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192SMALL_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_small_avx2)
+extern int PQCLEAN_CROSSRSDP192SMALL_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192SMALL_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP192SMALL_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_small_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192SMALL_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192SMALL_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_192_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_192_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192SMALL_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP192SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdp_256_balanced.c b/src/sig/cross/sig_cross_rsdp_256_balanced.c
new file mode 100644
index 000000000..3cd07a60b
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdp_256_balanced.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_balanced)
+
+OQS_SIG *OQS_SIG_cross_rsdp_256_balanced_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdp_256_balanced;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 5;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdp_256_balanced_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdp_256_balanced_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdp_256_balanced_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdp_256_balanced_keypair;
+ sig->sign = OQS_SIG_cross_rsdp_256_balanced_sign;
+ sig->verify = OQS_SIG_cross_rsdp_256_balanced_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDP256BALANCED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256BALANCED_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256BALANCED_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_balanced_avx2)
+extern int PQCLEAN_CROSSRSDP256BALANCED_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256BALANCED_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256BALANCED_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_balanced_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256BALANCED_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256BALANCED_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256BALANCED_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdp_256_fast.c b/src/sig/cross/sig_cross_rsdp_256_fast.c
new file mode 100644
index 000000000..3c954f9a2
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdp_256_fast.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_fast)
+
+OQS_SIG *OQS_SIG_cross_rsdp_256_fast_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdp_256_fast;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 5;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdp_256_fast_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdp_256_fast_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdp_256_fast_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdp_256_fast_keypair;
+ sig->sign = OQS_SIG_cross_rsdp_256_fast_sign;
+ sig->verify = OQS_SIG_cross_rsdp_256_fast_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDP256FAST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256FAST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256FAST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_fast_avx2)
+extern int PQCLEAN_CROSSRSDP256FAST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256FAST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256FAST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_fast_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256FAST_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256FAST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256FAST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdp_256_small.c b/src/sig/cross/sig_cross_rsdp_256_small.c
new file mode 100644
index 000000000..f20039a91
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdp_256_small.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_small)
+
+OQS_SIG *OQS_SIG_cross_rsdp_256_small_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdp_256_small;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 5;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdp_256_small_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdp_256_small_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdp_256_small_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdp_256_small_keypair;
+ sig->sign = OQS_SIG_cross_rsdp_256_small_sign;
+ sig->verify = OQS_SIG_cross_rsdp_256_small_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDP256SMALL_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256SMALL_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256SMALL_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_small_avx2)
+extern int PQCLEAN_CROSSRSDP256SMALL_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256SMALL_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDP256SMALL_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_small_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256SMALL_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256SMALL_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdp_256_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdp_256_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256SMALL_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDP256SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdpg_128_balanced.c b/src/sig/cross/sig_cross_rsdpg_128_balanced.c
new file mode 100644
index 000000000..287784771
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdpg_128_balanced.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_balanced)
+
+OQS_SIG *OQS_SIG_cross_rsdpg_128_balanced_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdpg_128_balanced;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 1;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdpg_128_balanced_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdpg_128_balanced_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdpg_128_balanced_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdpg_128_balanced_keypair;
+ sig->sign = OQS_SIG_cross_rsdpg_128_balanced_sign;
+ sig->verify = OQS_SIG_cross_rsdpg_128_balanced_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDPG128BALANCED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128BALANCED_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128BALANCED_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_balanced_avx2)
+extern int PQCLEAN_CROSSRSDPG128BALANCED_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128BALANCED_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128BALANCED_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_balanced_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128BALANCED_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128BALANCED_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128BALANCED_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdpg_128_fast.c b/src/sig/cross/sig_cross_rsdpg_128_fast.c
new file mode 100644
index 000000000..cf10d6298
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdpg_128_fast.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_fast)
+
+OQS_SIG *OQS_SIG_cross_rsdpg_128_fast_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdpg_128_fast;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 1;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdpg_128_fast_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdpg_128_fast_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdpg_128_fast_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdpg_128_fast_keypair;
+ sig->sign = OQS_SIG_cross_rsdpg_128_fast_sign;
+ sig->verify = OQS_SIG_cross_rsdpg_128_fast_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDPG128FAST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128FAST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128FAST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_fast_avx2)
+extern int PQCLEAN_CROSSRSDPG128FAST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128FAST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128FAST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_fast_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128FAST_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128FAST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128FAST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdpg_128_small.c b/src/sig/cross/sig_cross_rsdpg_128_small.c
new file mode 100644
index 000000000..e2cab5d43
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdpg_128_small.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_small)
+
+OQS_SIG *OQS_SIG_cross_rsdpg_128_small_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdpg_128_small;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 1;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdpg_128_small_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdpg_128_small_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdpg_128_small_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdpg_128_small_keypair;
+ sig->sign = OQS_SIG_cross_rsdpg_128_small_sign;
+ sig->verify = OQS_SIG_cross_rsdpg_128_small_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDPG128SMALL_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128SMALL_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128SMALL_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_small_avx2)
+extern int PQCLEAN_CROSSRSDPG128SMALL_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128SMALL_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG128SMALL_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_small_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128SMALL_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128SMALL_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_128_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_128_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128SMALL_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG128SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdpg_192_balanced.c b/src/sig/cross/sig_cross_rsdpg_192_balanced.c
new file mode 100644
index 000000000..e85be184b
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdpg_192_balanced.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_balanced)
+
+OQS_SIG *OQS_SIG_cross_rsdpg_192_balanced_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdpg_192_balanced;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 3;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdpg_192_balanced_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdpg_192_balanced_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdpg_192_balanced_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdpg_192_balanced_keypair;
+ sig->sign = OQS_SIG_cross_rsdpg_192_balanced_sign;
+ sig->verify = OQS_SIG_cross_rsdpg_192_balanced_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDPG192BALANCED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192BALANCED_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192BALANCED_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_balanced_avx2)
+extern int PQCLEAN_CROSSRSDPG192BALANCED_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192BALANCED_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192BALANCED_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_balanced_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192BALANCED_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192BALANCED_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192BALANCED_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdpg_192_fast.c b/src/sig/cross/sig_cross_rsdpg_192_fast.c
new file mode 100644
index 000000000..4c600ae14
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdpg_192_fast.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_fast)
+
+OQS_SIG *OQS_SIG_cross_rsdpg_192_fast_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdpg_192_fast;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 3;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdpg_192_fast_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdpg_192_fast_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdpg_192_fast_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdpg_192_fast_keypair;
+ sig->sign = OQS_SIG_cross_rsdpg_192_fast_sign;
+ sig->verify = OQS_SIG_cross_rsdpg_192_fast_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDPG192FAST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192FAST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192FAST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_fast_avx2)
+extern int PQCLEAN_CROSSRSDPG192FAST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192FAST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192FAST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_fast_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192FAST_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192FAST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192FAST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdpg_192_small.c b/src/sig/cross/sig_cross_rsdpg_192_small.c
new file mode 100644
index 000000000..624f02e45
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdpg_192_small.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_small)
+
+OQS_SIG *OQS_SIG_cross_rsdpg_192_small_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdpg_192_small;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 3;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdpg_192_small_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdpg_192_small_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdpg_192_small_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdpg_192_small_keypair;
+ sig->sign = OQS_SIG_cross_rsdpg_192_small_sign;
+ sig->verify = OQS_SIG_cross_rsdpg_192_small_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDPG192SMALL_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192SMALL_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192SMALL_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_small_avx2)
+extern int PQCLEAN_CROSSRSDPG192SMALL_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192SMALL_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG192SMALL_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_small_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192SMALL_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192SMALL_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_192_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_192_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192SMALL_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG192SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdpg_256_balanced.c b/src/sig/cross/sig_cross_rsdpg_256_balanced.c
new file mode 100644
index 000000000..73f12fafb
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdpg_256_balanced.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_balanced)
+
+OQS_SIG *OQS_SIG_cross_rsdpg_256_balanced_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdpg_256_balanced;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 5;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdpg_256_balanced_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdpg_256_balanced_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdpg_256_balanced_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdpg_256_balanced_keypair;
+ sig->sign = OQS_SIG_cross_rsdpg_256_balanced_sign;
+ sig->verify = OQS_SIG_cross_rsdpg_256_balanced_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDPG256BALANCED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256BALANCED_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256BALANCED_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_balanced_avx2)
+extern int PQCLEAN_CROSSRSDPG256BALANCED_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256BALANCED_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256BALANCED_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_balanced_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256BALANCED_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256BALANCED_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_balanced_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256BALANCED_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256BALANCED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_balanced_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_balanced_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256BALANCED_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256BALANCED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdpg_256_fast.c b/src/sig/cross/sig_cross_rsdpg_256_fast.c
new file mode 100644
index 000000000..1ebfa2c22
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdpg_256_fast.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_fast)
+
+OQS_SIG *OQS_SIG_cross_rsdpg_256_fast_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdpg_256_fast;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 5;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdpg_256_fast_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdpg_256_fast_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdpg_256_fast_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdpg_256_fast_keypair;
+ sig->sign = OQS_SIG_cross_rsdpg_256_fast_sign;
+ sig->verify = OQS_SIG_cross_rsdpg_256_fast_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDPG256FAST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256FAST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256FAST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_fast_avx2)
+extern int PQCLEAN_CROSSRSDPG256FAST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256FAST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256FAST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_fast_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256FAST_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256FAST_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_fast_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256FAST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256FAST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_fast_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_fast_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256FAST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256FAST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/sig_cross_rsdpg_256_small.c b/src/sig/cross/sig_cross_rsdpg_256_small.c
new file mode 100644
index 000000000..6f105167e
--- /dev/null
+++ b/src/sig/cross/sig_cross_rsdpg_256_small.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+#include
+
+#include
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_small)
+
+OQS_SIG *OQS_SIG_cross_rsdpg_256_small_new(void) {
+
+ OQS_SIG *sig = malloc(sizeof(OQS_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->method_name = OQS_SIG_alg_cross_rsdpg_256_small;
+ sig->alg_version = "1.2 + Keccak_x4 + PQClean fixes";
+
+ sig->claimed_nist_level = 5;
+ sig->euf_cma = true;
+
+ sig->length_public_key = OQS_SIG_cross_rsdpg_256_small_length_public_key;
+ sig->length_secret_key = OQS_SIG_cross_rsdpg_256_small_length_secret_key;
+ sig->length_signature = OQS_SIG_cross_rsdpg_256_small_length_signature;
+
+ sig->keypair = OQS_SIG_cross_rsdpg_256_small_keypair;
+ sig->sign = OQS_SIG_cross_rsdpg_256_small_sign;
+ sig->verify = OQS_SIG_cross_rsdpg_256_small_verify;
+
+ return sig;
+}
+
+extern int PQCLEAN_CROSSRSDPG256SMALL_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256SMALL_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256SMALL_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_small_avx2)
+extern int PQCLEAN_CROSSRSDPG256SMALL_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256SMALL_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk);
+extern int PQCLEAN_CROSSRSDPG256SMALL_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk);
+#endif
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_small_keypair(uint8_t *public_key, uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256SMALL_AVX2_crypto_sign_keypair(public_key, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256SMALL_CLEAN_crypto_sign_keypair(public_key, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_small_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256SMALL_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256SMALL_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key);
+#endif
+}
+
+OQS_API OQS_STATUS OQS_SIG_cross_rsdpg_256_small_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
+#if defined(OQS_ENABLE_SIG_cross_rsdpg_256_small_avx2)
+#if defined(OQS_DIST_BUILD)
+ if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
+#endif /* OQS_DIST_BUILD */
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256SMALL_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#if defined(OQS_DIST_BUILD)
+ } else {
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+ }
+#endif /* OQS_DIST_BUILD */
+#else
+ return (OQS_STATUS) PQCLEAN_CROSSRSDPG256SMALL_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key);
+#endif
+}
+
+#endif
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/CROSS.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/CROSS.c
new file mode 100644
index 000000000..ec0add723
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/CROSS.c
@@ -0,0 +1,553 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+#include
+#include
+
+#include "architecture_detect.h"
+#include "CROSS.h"
+#include "csprng_hash.h"
+#include "fq_arith.h"
+#include "merkle_tree.h"
+#include "pack_unpack.h"
+#include "randombytes.h"
+#include "seedtree.h"
+
+static
+void expand_public_seed(FQ_ELEM V_tr[K][N - K],
+ const uint8_t seed_pub[KEYPAIR_SEED_LENGTH_BYTES]) {
+ CSPRNG_STATE_T CSPRNG_state_mat;
+ initialize_csprng(&CSPRNG_state_mat, seed_pub, KEYPAIR_SEED_LENGTH_BYTES);
+ CSPRNG_fq_mat(V_tr, &CSPRNG_state_mat);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_mat);
+}
+
+static
+void expand_private_seed(FZ_ELEM eta[N],
+ FQ_ELEM V_tr[K][N - K],
+ const uint8_t seed[KEYPAIR_SEED_LENGTH_BYTES]) {
+ uint8_t seede_seed_pub[2][KEYPAIR_SEED_LENGTH_BYTES];
+ CSPRNG_STATE_T CSPRNG_state;
+ initialize_csprng(&CSPRNG_state, seed, KEYPAIR_SEED_LENGTH_BYTES);
+ csprng_randombytes((uint8_t *)seede_seed_pub,
+ 2 * KEYPAIR_SEED_LENGTH_BYTES,
+ &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ expand_public_seed(V_tr, seede_seed_pub[1]);
+
+ CSPRNG_STATE_T CSPRNG_state_eta;
+ initialize_csprng(&CSPRNG_state_eta, seede_seed_pub[0], KEYPAIR_SEED_LENGTH_BYTES);
+ CSPRNG_zz_vec(eta, &CSPRNG_state_eta);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_eta);
+}
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_CROSS_keygen(prikey_t *SK,
+ pubkey_t *PK) {
+ /* generation of random material for public and private key */
+ randombytes(SK->seed, KEYPAIR_SEED_LENGTH_BYTES);
+ uint8_t seede_seed_pub[2][KEYPAIR_SEED_LENGTH_BYTES];
+
+ CSPRNG_STATE_T CSPRNG_state;
+ initialize_csprng(&CSPRNG_state, SK->seed, KEYPAIR_SEED_LENGTH_BYTES);
+ csprng_randombytes((uint8_t *)seede_seed_pub,
+ 2 * KEYPAIR_SEED_LENGTH_BYTES,
+ &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ memcpy(PK->seed_pub, seede_seed_pub[1], KEYPAIR_SEED_LENGTH_BYTES);
+
+ /* expansion of matrix/matrices */
+ FQ_ELEM V_tr[K][N - K];
+ expand_public_seed(V_tr, PK->seed_pub);
+
+ /* expansion of secret key material */
+ FZ_ELEM eta[N];
+ CSPRNG_STATE_T CSPRNG_state_eta;
+ initialize_csprng(&CSPRNG_state_eta, seede_seed_pub[0], KEYPAIR_SEED_LENGTH_BYTES);
+
+ CSPRNG_zz_vec(eta, &CSPRNG_state_eta);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_eta);
+
+ /* compute public syndrome */
+ FQ_ELEM pub_syn[N - K];
+ restr_vec_by_fq_matrix(pub_syn, eta, V_tr);
+ fq_dz_norm_synd(pub_syn);
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_syn(PK->s, pub_syn);
+}
+
+/* sign cannot fail */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_CROSS_sign(const prikey_t *const SK,
+ const char *const m,
+ const size_t mlen,
+ CROSS_sig_t *const sig) {
+ /* Wipe any residual information in the sig structure allocated by the
+ * caller */
+ memset(sig, 0, sizeof(CROSS_sig_t));
+ /* Key material expansion */
+ FQ_ELEM V_tr[K][N - K];
+ FZ_ELEM eta[N];
+ expand_private_seed(eta, V_tr, SK->seed);
+
+ /* Expanded */
+ alignas(EPI8_PER_REG) uint16_t V_tr_avx[K][ROUND_UP(N - K, EPI16_PER_REG)] = {{0}};
+ for (int i = 0; i < K; i++) {
+ for (int j = 0; j < N - K; j++) {
+ V_tr_avx[i][j] = V_tr[i][j];
+ }
+ }
+
+ uint8_t root_seed[SEED_LENGTH_BYTES];
+ randombytes(root_seed, SEED_LENGTH_BYTES);
+ randombytes(sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t seed_tree[SEED_LENGTH_BYTES * NUM_NODES_SEED_TREE] = {0};
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_generate_seed_tree_from_root(seed_tree, root_seed, sig->salt);
+ uint8_t *rounds_seeds = seed_tree +
+ SEED_LENGTH_BYTES * NUM_INNER_NODES_SEED_TREE;
+
+ FZ_ELEM eta_tilde[T][N];
+ FZ_ELEM sigma[T][N];
+ FQ_ELEM u_tilde[T][N];
+ FQ_ELEM s_tilde[N - K];
+
+ uint8_t cmt_0_i_input[4][DENSELY_PACKED_FQ_SYN_SIZE +
+ DENSELY_PACKED_FZ_VEC_SIZE +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ const int offset_salt = DENSELY_PACKED_FQ_SYN_SIZE + DENSELY_PACKED_FZ_VEC_SIZE;
+ const int offset_round_idx = offset_salt + SALT_LENGTH_BYTES;
+
+ uint8_t cmt_1_i_input[4][SEED_LENGTH_BYTES +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+
+ /* place the salt in the hash input for all parallel instances of keccak */
+ for (int instance = 0; instance < 4; instance++) {
+ /* cmt_0_i_input is syndrome||sigma ||salt ; place salt at the end */
+ memcpy(cmt_0_i_input[instance] + offset_salt, sig->salt, SALT_LENGTH_BYTES);
+ /* cmt_1_i_input is concat(seed,salt,round index) */
+ memcpy(cmt_1_i_input[instance] + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ }
+
+ uint8_t cmt_0[T][HASH_DIGEST_LENGTH] = {0};
+ uint8_t cmt_1[T][HASH_DIGEST_LENGTH] = {0};
+
+ /* enqueue the calls to hash */
+ int to_hash = 0;
+ int round_idx_queue[4] = {0};
+
+ CSPRNG_STATE_T CSPRNG_state;
+ for (uint16_t i = 0; i < T; i++) {
+ to_hash++;
+ round_idx_queue[to_hash - 1] = i;
+ /* CSPRNG is fed with concat(seed,salt,round index) represented
+ * as a 2 bytes little endian unsigned integer */
+ uint8_t csprng_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ memcpy(csprng_input, rounds_seeds + SEED_LENGTH_BYTES * i, SEED_LENGTH_BYTES);
+ memcpy(csprng_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ /* i+c */
+ uint16_t domain_sep_i = i + NUM_NODES_SEED_TREE;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES] = (domain_sep_i >> 8) & 0xFF;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + 1] = domain_sep_i & 0xFF;
+
+ /* expand seed[i] into seed_e and seed_u */
+ initialize_csprng(&CSPRNG_state,
+ csprng_input,
+ SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t));
+ /* expand eta_tilde */
+ CSPRNG_zz_vec(eta_tilde[i], &CSPRNG_state);
+ restr_vec_sub(sigma[i], eta, eta_tilde[i]);
+
+ FQ_ELEM v[N];
+ convert_restr_vec_to_fq(v, sigma[i]);
+ fz_dz_norm_sigma(sigma[i]);
+ /* expand u_tilde */
+ CSPRNG_fq_vec(u_tilde[i], &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ FQ_ELEM u[N];
+ fq_vec_by_fq_vec_pointwise(u, v, u_tilde[i]);
+ fq_vec_by_fq_matrix(s_tilde, u, V_tr_avx);
+ fq_dz_norm_synd(s_tilde);
+
+ /* cmt_0_i_input contains s-tilde || sigma_i || salt */
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_syn(cmt_0_i_input[to_hash - 1], s_tilde);
+
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fz_vec(cmt_0_i_input[to_hash - 1] + DENSELY_PACKED_FQ_SYN_SIZE, sigma[i]);
+ /* i+c+dsc */
+ uint16_t domain_sep_idx_hash = domain_sep_i + HASH_CSPRNG_DOMAIN_SEP_CONST;
+ /* Fixed endianness marshalling of round counter */
+ cmt_0_i_input[to_hash - 1][offset_round_idx] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_0_i_input[to_hash - 1][offset_round_idx + 1] = domain_sep_idx_hash & 0xFF;
+
+ memcpy(cmt_1_i_input[to_hash - 1],
+ rounds_seeds + SEED_LENGTH_BYTES * i,
+ SEED_LENGTH_BYTES);
+
+ cmt_1_i_input[to_hash - 1][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_1_i_input[to_hash - 1][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + 1] = domain_sep_idx_hash & 0xFF;
+
+ if (to_hash == 4 || i == T - 1) {
+ par_hash(
+ to_hash,
+ cmt_0[round_idx_queue[0]],
+ cmt_0[round_idx_queue[1]],
+ cmt_0[round_idx_queue[2]],
+ cmt_0[round_idx_queue[3]],
+ cmt_0_i_input[0],
+ cmt_0_i_input[1],
+ cmt_0_i_input[2],
+ cmt_0_i_input[3],
+ sizeof(cmt_0_i_input) / 4
+ );
+ par_hash(
+ to_hash,
+ cmt_1[round_idx_queue[0]],
+ cmt_1[round_idx_queue[1]],
+ cmt_1[round_idx_queue[2]],
+ cmt_1[round_idx_queue[3]],
+ cmt_1_i_input[0],
+ cmt_1_i_input[1],
+ cmt_1_i_input[2],
+ cmt_1_i_input[3],
+ sizeof(cmt_1_i_input) / 4
+ );
+ to_hash = 0;
+ }
+ }
+
+ /* vector containing d_0 and d_1 from spec */
+ uint8_t commit_digests[2][HASH_DIGEST_LENGTH];
+ uint8_t merkle_tree_0[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH];
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_merkle_tree_root_compute(commit_digests[0], merkle_tree_0, cmt_0);
+ hash(commit_digests[1], (unsigned char *)cmt_1, sizeof(cmt_1));
+ hash(sig->digest_01,
+ (unsigned char *) commit_digests,
+ sizeof(commit_digests));
+
+ /* first challenge extraction */
+ uint8_t beta_buf[2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES];
+ /* place d_m at the beginning of the input of the hash generating d_beta*/
+ hash(beta_buf, (uint8_t *) m, mlen);
+ memcpy(beta_buf + HASH_DIGEST_LENGTH, sig->digest_01, HASH_DIGEST_LENGTH);
+ memcpy(beta_buf + 2 * HASH_DIGEST_LENGTH, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t d_beta[HASH_DIGEST_LENGTH];
+ hash(d_beta, beta_buf, 2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES);
+
+ FQ_ELEM beta[T];
+ initialize_csprng(&CSPRNG_state, d_beta, HASH_DIGEST_LENGTH);
+ CSPRNG_fq_vec_beta(beta, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ /* Computation of the first round of responses */
+ FQ_ELEM y[T][N];
+ for (int i = 0; i < T; i++) {
+ fq_vec_by_restr_vec_scaled(y[i],
+ eta_tilde[i],
+ beta[i],
+ u_tilde[i]);
+ fq_dz_norm(y[i]);
+ }
+ /* y vectors are packed before being hashed */
+ uint8_t digest_b_buf[T * DENSELY_PACKED_FQ_VEC_SIZE + HASH_DIGEST_LENGTH];
+ for (int x = 0; x < T; x++) {
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_vec(digest_b_buf + (x * DENSELY_PACKED_FQ_VEC_SIZE), y[x]);
+ }
+ /* Second challenge extraction */
+ memcpy(digest_b_buf + T * DENSELY_PACKED_FQ_VEC_SIZE, d_beta, HASH_DIGEST_LENGTH);
+
+ hash(sig->digest_b, digest_b_buf, sizeof(digest_b_buf));
+
+ uint8_t fixed_weight_b[T] = {0};
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_expand_digest_to_fixed_weight(fixed_weight_b, sig->digest_b);
+
+ /* Computation of the second round of responses */
+
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_merkle_tree_proof_compute(sig->mtp, merkle_tree_0, fixed_weight_b);
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_publish_seeds(sig->stp, seed_tree, fixed_weight_b);
+
+ int published_rsps = 0;
+ for (int i = 0; i < T; i++) {
+ if (fixed_weight_b[i] == 0) {
+ /* PQClean-edit: remove assertion */
+ //assert(published_rsps < T-W);
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_vec(sig->rsp_0[published_rsps].y, y[i]);
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fz_vec(sig->rsp_0[published_rsps].sigma, sigma[i]);
+ memcpy(sig->rsp_1[published_rsps], cmt_1[i], HASH_DIGEST_LENGTH);
+ published_rsps++;
+ }
+ }
+}
+
+/* PQClean-edit: avoid VLA */
+#define CSPRNG_INPUT_LENGTH (SALT_LENGTH_BYTES+SEED_LENGTH_BYTES+SIZEOF_UINT16)
+//const int csprng_input_length = SALT_LENGTH_BYTES+SEED_LENGTH_BYTES+sizeof(uint16_t);
+
+/* verify returns 1 if signature is ok, 0 otherwise */
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_CROSS_verify(const pubkey_t *const PK,
+ const char *const m,
+ const size_t mlen,
+ const CROSS_sig_t *const sig) {
+ CSPRNG_STATE_T CSPRNG_state;
+
+ FQ_ELEM V_tr[K][N - K];
+ expand_public_seed(V_tr, PK->seed_pub);
+ /* Expanded */
+ alignas(EPI8_PER_REG) uint16_t V_tr_avx[K][ROUND_UP(N - K, EPI16_PER_REG)] = {{0}};
+ for (int i = 0; i < K; i++) {
+ for (int j = 0; j < N - K; j++) {
+ V_tr_avx[i][j] = V_tr[i][j];
+ }
+ }
+
+ FQ_ELEM pub_syn[N - K];
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fq_syn(pub_syn, PK->s);
+
+ uint8_t beta_buf[2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES];
+ hash(beta_buf, (uint8_t *) m, mlen);
+ memcpy(beta_buf + HASH_DIGEST_LENGTH, sig->digest_01, HASH_DIGEST_LENGTH);
+ memcpy(beta_buf + 2 * HASH_DIGEST_LENGTH, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t d_beta[HASH_DIGEST_LENGTH];
+ hash(d_beta, beta_buf, sizeof(beta_buf));
+
+ FQ_ELEM beta[T];
+ initialize_csprng(&CSPRNG_state, d_beta, HASH_DIGEST_LENGTH);
+ CSPRNG_fq_vec_beta(beta, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ uint8_t fixed_weight_b[T] = {0};
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_expand_digest_to_fixed_weight(fixed_weight_b, sig->digest_b);
+
+ uint8_t seed_tree[SEED_LENGTH_BYTES * NUM_NODES_SEED_TREE] = {0};
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_regenerate_round_seeds(seed_tree, fixed_weight_b, sig->stp, sig->salt);
+ uint8_t *rounds_seeds = seed_tree +
+ SEED_LENGTH_BYTES * NUM_INNER_NODES_SEED_TREE;
+
+ uint8_t cmt_0_i_input[4][DENSELY_PACKED_FQ_SYN_SIZE +
+ DENSELY_PACKED_FZ_VEC_SIZE +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ const int offset_salt = DENSELY_PACKED_FQ_SYN_SIZE + DENSELY_PACKED_FZ_VEC_SIZE;
+ const int offset_round_idx = offset_salt + SALT_LENGTH_BYTES;
+
+ uint8_t cmt_1_i_input[4][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t)];
+
+ /* place the salt in the hash input for all parallel instances of keccak */
+ for (int instance = 0; instance < 4; instance++) {
+ /* cmt_0_i_input is syndrome||sigma ||salt */
+ memcpy(cmt_0_i_input[instance] + offset_salt, sig->salt, SALT_LENGTH_BYTES);
+ /* cmt_1_i_input is concat(seed,salt,round index) */
+ memcpy(cmt_1_i_input[instance] + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ }
+
+ uint8_t cmt_0[T][HASH_DIGEST_LENGTH] = {0};
+ uint8_t cmt_1[T][HASH_DIGEST_LENGTH] = {0};
+
+ FZ_ELEM eta_tilde[N];
+ FQ_ELEM u_tilde[N];
+
+ FQ_ELEM y_tilde[N] = {0};
+ FQ_ELEM s_tilde[N - K] = {0};
+
+ FQ_ELEM y[T][N];
+
+ /* enqueue the calls to hash */
+ int to_hash_cmt_1 = 0;
+ int to_hash_cmt_0 = 0;
+ int round_idx_queue_cmt_1[4] = {0};
+ int round_idx_queue_cmt_0[4] = {0};
+
+ int used_rsps = 0;
+ int is_signature_ok = 1;
+ for (uint16_t i = 0; i < T; i++) {
+
+ /* i+c */
+ uint16_t domain_sep_i = i + NUM_NODES_SEED_TREE;
+ /* i+c+dsc */
+ uint16_t domain_sep_idx_hash = domain_sep_i + HASH_CSPRNG_DOMAIN_SEP_CONST;
+
+ if (fixed_weight_b[i] == 1) {
+
+ /* save the index for the hash output */
+ to_hash_cmt_1++;
+ round_idx_queue_cmt_1[to_hash_cmt_1 - 1] = i;
+
+ memcpy(cmt_1_i_input[to_hash_cmt_1 - 1],
+ rounds_seeds + SEED_LENGTH_BYTES * i,
+ SEED_LENGTH_BYTES);
+
+ cmt_1_i_input[to_hash_cmt_1 - 1][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_1_i_input[to_hash_cmt_1 - 1][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + 1] = domain_sep_idx_hash & 0xFF;
+
+ /* CSPRNG is fed with concat(seed,salt,round index) represented
+ * as a 2 bytes little endian unsigned integer */
+ uint8_t csprng_input[CSPRNG_INPUT_LENGTH];
+ memcpy(csprng_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ memcpy(csprng_input, rounds_seeds + SEED_LENGTH_BYTES * i, SEED_LENGTH_BYTES);
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES] = (domain_sep_i >> 8) & 0xFF;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + 1] = domain_sep_i & 0xFF;
+
+ /* expand seed[i] into seed_e and seed_u */
+ initialize_csprng(&CSPRNG_state, csprng_input, CSPRNG_INPUT_LENGTH);
+ /* expand eta_tilde */
+ CSPRNG_zz_vec(eta_tilde, &CSPRNG_state);
+ /* expand u_tilde */
+ CSPRNG_fq_vec(u_tilde, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ fq_vec_by_restr_vec_scaled(y[i],
+ eta_tilde,
+ beta[i],
+ u_tilde);
+ fq_dz_norm(y[i]);
+ } else {
+
+ /* save the index for the hash output */
+ to_hash_cmt_0++;
+ round_idx_queue_cmt_0[to_hash_cmt_0 - 1] = i;
+
+ /* place y[i] in the buffer for later on hashing */
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fq_vec(y[i], sig->rsp_0[used_rsps].y);
+
+ FZ_ELEM sigma_local[N];
+ /*sigma is memcpy'ed directly into cmt_0 input buffer */
+ FZ_ELEM *sigma_ptr = cmt_0_i_input[to_hash_cmt_0 - 1] + DENSELY_PACKED_FQ_SYN_SIZE;
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fz_vec(sigma_local, sig->rsp_0[used_rsps].sigma);
+ memcpy(sigma_ptr,
+ &sig->rsp_0[used_rsps].sigma,
+ DENSELY_PACKED_FZ_VEC_SIZE);
+ is_signature_ok = is_signature_ok &&
+ is_zz_vec_in_restr_group(sigma_local);
+ memcpy(cmt_1[i], sig->rsp_1[used_rsps], HASH_DIGEST_LENGTH);
+ used_rsps++;
+
+ FQ_ELEM v[N];
+ convert_restr_vec_to_fq(v, sigma_local);
+ fq_vec_by_fq_vec_pointwise(y_tilde, v, y[i]);
+ fq_vec_by_fq_matrix(s_tilde, y_tilde, V_tr_avx);
+ fq_dz_norm_synd(s_tilde);
+ FQ_ELEM to_compress[N - K];
+ fq_synd_minus_fq_vec_scaled(to_compress,
+ s_tilde,
+ beta[i],
+ pub_syn);
+ fq_dz_norm_synd(to_compress);
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_syn(cmt_0_i_input[to_hash_cmt_0 - 1], to_compress);
+ cmt_0_i_input[to_hash_cmt_0 - 1][offset_round_idx] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_0_i_input[to_hash_cmt_0 - 1][offset_round_idx + 1] = domain_sep_idx_hash & 0xFF;
+
+ }
+ /* hash committment 1 in batches of 4 (or less on the last round) */
+ if (to_hash_cmt_1 == 4 || i == T - 1) {
+ par_hash(
+ to_hash_cmt_1,
+ cmt_1[round_idx_queue_cmt_1[0]],
+ cmt_1[round_idx_queue_cmt_1[1]],
+ cmt_1[round_idx_queue_cmt_1[2]],
+ cmt_1[round_idx_queue_cmt_1[3]],
+ cmt_1_i_input[0],
+ cmt_1_i_input[1],
+ cmt_1_i_input[2],
+ cmt_1_i_input[3],
+ sizeof(cmt_1_i_input) / 4
+ );
+ to_hash_cmt_1 = 0;
+ }
+ /* hash committment 0 in batches of 4 (or less on the last round) */
+ if (to_hash_cmt_0 == 4 || i == T - 1) {
+ par_hash(
+ to_hash_cmt_0,
+ cmt_0[round_idx_queue_cmt_0[0]],
+ cmt_0[round_idx_queue_cmt_0[1]],
+ cmt_0[round_idx_queue_cmt_0[2]],
+ cmt_0[round_idx_queue_cmt_0[3]],
+ cmt_0_i_input[0],
+ cmt_0_i_input[1],
+ cmt_0_i_input[2],
+ cmt_0_i_input[3],
+ sizeof(cmt_0_i_input) / 4
+ );
+ to_hash_cmt_0 = 0;
+ }
+ } /* end for iterating on ZKID iterations */
+
+ /* PQClean-edit: remove assertion */
+ //assert(is_signature_ok);
+
+ uint8_t commit_digests[2][HASH_DIGEST_LENGTH];
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_merkle_tree_root_recompute(commit_digests[0],
+ cmt_0,
+ sig->mtp,
+ fixed_weight_b);
+ hash(commit_digests[1], (unsigned char *)cmt_1, sizeof(cmt_1));
+
+ uint8_t digest_01_recomputed[HASH_DIGEST_LENGTH];
+ hash(digest_01_recomputed,
+ (unsigned char *) commit_digests,
+ sizeof(commit_digests));
+
+ uint8_t digest_b_buf[T * DENSELY_PACKED_FQ_VEC_SIZE + HASH_DIGEST_LENGTH];
+ for (int x = 0; x < T; x++) {
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_vec(digest_b_buf + (x * DENSELY_PACKED_FQ_VEC_SIZE), y[x]);
+ }
+ memcpy(digest_b_buf + T * DENSELY_PACKED_FQ_VEC_SIZE, d_beta, HASH_DIGEST_LENGTH);
+
+ uint8_t digest_b_recomputed[HASH_DIGEST_LENGTH];
+ hash(digest_b_recomputed, digest_b_buf, sizeof(digest_b_buf));
+
+ int does_digest_01_match = ( memcmp(digest_01_recomputed,
+ sig->digest_01,
+ HASH_DIGEST_LENGTH) == 0);
+ /* PQClean-edit: remove assertion */
+ //assert(does_digest_01_match);
+
+ int does_digest_b_match = ( memcmp(digest_b_recomputed,
+ sig->digest_b,
+ HASH_DIGEST_LENGTH) == 0);
+ /* PQClean-edit: remove assertion */
+ //assert(does_digest_b_match);
+
+ is_signature_ok = is_signature_ok &&
+ does_digest_01_match &&
+ does_digest_b_match;
+ return is_signature_ok;
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/CROSS.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/CROSS.h
new file mode 100644
index 000000000..8b716b31a
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/CROSS.h
@@ -0,0 +1,76 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+#pragma once
+
+#include
+
+#include "pack_unpack.h"
+#include "parameters.h"
+
+/* Public key: the parity check matrix is shrunk to a seed, syndrome
+ * represented in full */
+typedef struct {
+ uint8_t seed_pub[KEYPAIR_SEED_LENGTH_BYTES];
+ uint8_t s[DENSELY_PACKED_FQ_SYN_SIZE];
+} pubkey_t;
+
+/* Private key: just a single seed*/
+typedef struct {
+ uint8_t seed[KEYPAIR_SEED_LENGTH_BYTES];
+} prikey_t;
+
+typedef struct {
+ uint8_t y[DENSELY_PACKED_FQ_VEC_SIZE];
+ uint8_t sigma[DENSELY_PACKED_FZ_VEC_SIZE];
+} rsp_0_t;
+
+/* Signature: */
+typedef struct {
+ uint8_t salt[SALT_LENGTH_BYTES];
+ uint8_t digest_01[HASH_DIGEST_LENGTH];
+ uint8_t digest_b[HASH_DIGEST_LENGTH];
+ /*Seed tree paths storage*/
+ uint8_t stp[TREE_NODES_TO_STORE * SEED_LENGTH_BYTES];
+ /*Merkle tree proof field.*/
+ uint8_t mtp[HASH_DIGEST_LENGTH * TREE_NODES_TO_STORE];
+ rsp_0_t rsp_0[T - W];
+ uint8_t rsp_1[T - W][HASH_DIGEST_LENGTH];
+} CROSS_sig_t;
+
+/* keygen cannot fail */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_CROSS_keygen(prikey_t *SK,
+ pubkey_t *PK);
+
+/* sign cannot fail */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_CROSS_sign(const prikey_t *SK,
+ const char *m,
+ size_t mlen,
+ CROSS_sig_t *sig);
+
+/* verify returns 1 if signature is ok, 0 otherwise */
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_CROSS_verify(const pubkey_t *PK,
+ const char *m,
+ size_t mlen,
+ const CROSS_sig_t *sig);
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/LICENSE b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/LICENSE
new file mode 100644
index 000000000..0e259d42c
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/LICENSE
@@ -0,0 +1,121 @@
+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/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/api.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/api.h
new file mode 100644
index 000000000..e93861eb6
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/api.h
@@ -0,0 +1,80 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#ifndef PQCLEAN_CROSSRSDP128BALANCED_AVX2_API_H
+#define PQCLEAN_CROSSRSDP128BALANCED_AVX2_API_H
+
+#pragma once
+
+#include
+#include
+
+#define PQCLEAN_CROSSRSDP128BALANCED_AVX2_CRYPTO_ALGNAME "cross-rsdp-128-balanced"
+
+/* no. of bytes of the secret key */
+#define PQCLEAN_CROSSRSDP128BALANCED_AVX2_CRYPTO_SECRETKEYBYTES 32
+
+/* no. of bytes of the public key */
+#define PQCLEAN_CROSSRSDP128BALANCED_AVX2_CRYPTO_PUBLICKEYBYTES 77
+
+/* no. of bytes of overhead in a signed message */
+#define PQCLEAN_CROSSRSDP128BALANCED_AVX2_CRYPTO_BYTES 12912
+
+/* required bytes of input randomness */
+#define PQCLEAN_CROSSRSDP128BALANCED_AVX2_CRYPTO_RANDOMBYTES 16
+
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_keypair(unsigned char *pk,
+ unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign(unsigned char *sm,
+ size_t *smlen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_open(unsigned char *m,
+ size_t *mlen,
+ const unsigned char *sm,
+ size_t smlen,
+ const unsigned char *pk
+ );
+
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_signature(unsigned char *sig,
+ size_t *siglen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_verify(const unsigned char *sig,
+ size_t siglen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *pk
+ );
+
+#endif
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/architecture_detect.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/architecture_detect.h
new file mode 100644
index 000000000..6372cedc3
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/architecture_detect.h
@@ -0,0 +1,13 @@
+
+#pragma once
+
+/* liboqs-edit: avoid checking for ISA extensions
+ * when compiling avx2 just assume that Intel Instrinsics are available */
+#include
+#include
+#include
+#include
+//#include // liboqs-edit: x86intrin.h is not available on Windows
+
+#define EPI8_PER_REG 32
+#define EPI16_PER_REG 16
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/csprng_hash.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/csprng_hash.c
new file mode 100644
index 000000000..02011ba99
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/csprng_hash.c
@@ -0,0 +1,82 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include
+
+#include "csprng_hash.h"
+
+#define POSITION_MASK (( (uint16_t)1 << BITS_TO_REPRESENT(T-1))-1)
+
+/* Fisher-Yates shuffle obtaining the entire required randomness in a single
+ * call */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_expand_digest_to_fixed_weight(uint8_t fixed_weight_string[T],
+ const uint8_t digest[HASH_DIGEST_LENGTH]) {
+ CSPRNG_STATE_T csprng_state;
+ initialize_csprng(&csprng_state,
+ (const unsigned char *) digest,
+ HASH_DIGEST_LENGTH);
+ uint8_t CSPRNG_buffer[ROUND_UP(BITS_CWSTR_RNG, 8) / 8];
+ csprng_randombytes(CSPRNG_buffer, ROUND_UP(BITS_CWSTR_RNG, 8) / 8, &csprng_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&csprng_state);
+
+ /* initialize CW string */
+ memset(fixed_weight_string, 1, W);
+ memset(fixed_weight_string + W, 0, T - W);
+
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ int pos_in_buf = 8;
+
+ int curr = 0;
+ while (curr < T) {
+ /* refill randomness buffer if needed */
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ /*we need to draw a number in 0... T-1-curr */
+ int bits_for_pos = BITS_TO_REPRESENT(T - 1 - curr);
+ uint64_t pos_mask = ( (uint64_t) 1 << bits_for_pos) - 1;
+ uint16_t candidate_pos = (sub_buffer & pos_mask);
+ if (candidate_pos < T - curr) {
+ int dest = curr + candidate_pos;
+ /* the position is admissible, swap */
+ uint8_t tmp = fixed_weight_string[curr];
+ fixed_weight_string[curr] = fixed_weight_string[dest];
+ fixed_weight_string[dest] = tmp;
+ curr++;
+ sub_buffer = sub_buffer >> bits_for_pos;
+ bits_in_sub_buf -= bits_for_pos;
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+} /* PQCLEAN_CROSSRSDP128BALANCED_AVX2_expand_digest_to_fixed_weight */
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/csprng_hash.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/csprng_hash.h
new file mode 100644
index 000000000..7892cfde2
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/csprng_hash.h
@@ -0,0 +1,420 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+#pragma once
+
+#include "parameters.h"
+#include "sha3.h"
+
+/************************* CSPRNG ********************************/
+
+#define CSPRNG_STATE_T SHAKE_STATE_STRUCT
+/* initializes a CSPRNG, given the seed and a state pointer */
+static inline
+void initialize_csprng(CSPRNG_STATE_T *const csprng_state,
+ const unsigned char *const seed,
+ const uint32_t seed_len_bytes) {
+ // the second parameter is the security level of the SHAKE instance
+ xof_shake_init(csprng_state, SEED_LENGTH_BYTES * 8);
+ xof_shake_update(csprng_state, seed, seed_len_bytes);
+ xof_shake_final(csprng_state);
+} /* end initialize_csprng */
+
+/* extracts xlen bytes from the CSPRNG, given the state */
+static inline
+void csprng_randombytes(unsigned char *const x,
+ uint64_t xlen,
+ CSPRNG_STATE_T *const csprng_state) {
+ xof_shake_extract(csprng_state, x, xlen);
+}
+
+/* PQClean-edit: CSPRNG release context */
+static inline
+void csprng_release(CSPRNG_STATE_T *const csprng_state) {
+ xof_shake_release(csprng_state);
+}
+
+/**************** Parallel CSPRNG (x2, x3, x4) ***********************/
+
+#define CSPRNG_X2_STATE_T SHAKE_X2_STATE_STRUCT
+/* CRSPRNG_x3 calls SHAKE_x4 and discards the fourth input/output */
+#define CSPRNG_X3_STATE_T SHAKE_X4_STATE_STRUCT
+#define CSPRNG_X4_STATE_T SHAKE_X4_STATE_STRUCT
+
+/* initialize */
+static inline
+void initialize_csprng_x2(CSPRNG_X2_STATE_T *const csprng_state, const unsigned char *const seed1, const unsigned char *const seed2, const uint32_t seed_len_bytes) {
+ xof_shake_x2_init(csprng_state);
+ xof_shake_x2_update(csprng_state, seed1, seed2, seed_len_bytes);
+ xof_shake_x2_final(csprng_state);
+}
+static inline
+void initialize_csprng_x3(CSPRNG_X3_STATE_T *const csprng_state, const unsigned char *const seed1, const unsigned char *const seed2, const unsigned char *const seed3, const uint32_t seed_len_bytes) {
+ /* to perform xof_x3 it's faster to call xof_x4 and discard the last output */
+ xof_shake_x4_init(csprng_state);
+ xof_shake_x4_update(csprng_state, seed1, seed2, seed3, seed3, seed_len_bytes);
+ xof_shake_x4_final(csprng_state);
+}
+static inline
+void initialize_csprng_x4(CSPRNG_X4_STATE_T *const csprng_state, const unsigned char *const seed1, const unsigned char *const seed2, const unsigned char *const seed3, const unsigned char *const seed4, const uint32_t seed_len_bytes) {
+ xof_shake_x4_init(csprng_state);
+ xof_shake_x4_update(csprng_state, seed1, seed2, seed3, seed4, seed_len_bytes);
+ xof_shake_x4_final(csprng_state);
+}
+/* randombytes */
+static inline
+void csprng_randombytes_x2(unsigned char *const x1, unsigned char *const x2, uint64_t xlen, CSPRNG_X2_STATE_T *const csprng_state) {
+ xof_shake_x2_extract(csprng_state, x1, x2, xlen);
+}
+static inline
+void csprng_randombytes_x3(unsigned char *const x1, unsigned char *const x2, unsigned char *const x3, uint64_t xlen, CSPRNG_X3_STATE_T *const csprng_state) {
+ /* to perform xof_x3 it's faster to call xof_x4 and discard the last output */
+ xof_shake_x4_extract(csprng_state, x1, x2, x3, x3, xlen);
+}
+static inline
+void csprng_randombytes_x4(unsigned char *const x1, unsigned char *const x2, unsigned char *const x3, unsigned char *const x4, uint64_t xlen, CSPRNG_X4_STATE_T *const csprng_state) {
+ xof_shake_x4_extract(csprng_state, x1, x2, x3, x4, xlen);
+}
+/* release */
+static inline
+void csprng_release_x2(CSPRNG_X2_STATE_T *const csprng_state) {
+ xof_shake_x2_release(csprng_state);
+}
+static inline
+void csprng_release_x3(CSPRNG_X3_STATE_T *const csprng_state) {
+ xof_shake_x4_release(csprng_state);
+}
+static inline
+void csprng_release_x4(CSPRNG_X4_STATE_T *const csprng_state) {
+ xof_shake_x4_release(csprng_state);
+}
+
+/************** Single API for Parallel CSPRNG *******************/
+
+#define PAR_CSPRNG_STATE_T par_shake_ctx
+
+static inline
+void par_initialize_csprng(int par_level, PAR_CSPRNG_STATE_T *const states, const unsigned char *const seed1, const unsigned char *const seed2, const unsigned char *const seed3, const unsigned char *const seed4, const uint32_t seed_len_bytes) {
+ if (par_level == 1) {
+ initialize_csprng(&(states->state1), seed1, seed_len_bytes);
+ } else if (par_level == 2) {
+ initialize_csprng_x2(&(states->state2), seed1, seed2, seed_len_bytes);
+ } else if (par_level == 3) {
+ initialize_csprng_x3(&(states->state4), seed1, seed2, seed3, seed_len_bytes);
+ } else if (par_level == 4) {
+ initialize_csprng_x4(&(states->state4), seed1, seed2, seed3, seed4, seed_len_bytes);
+ }
+}
+static inline
+void par_csprng_randombytes(int par_level, PAR_CSPRNG_STATE_T *const states, unsigned char *const x1, unsigned char *const x2, unsigned char *const x3, unsigned char *const x4, uint64_t xlen) {
+ if (par_level == 1) {
+ csprng_randombytes(x1, xlen, &(states->state1));
+ } else if (par_level == 2) {
+ csprng_randombytes_x2(x1, x2, xlen, &(states->state2));
+ } else if (par_level == 3) {
+ csprng_randombytes_x3(x1, x2, x3, xlen, &(states->state4));
+ } else if (par_level == 4) {
+ csprng_randombytes_x4(x1, x2, x3, x4, xlen, &(states->state4));
+ }
+}
+static inline
+void par_csprng_release(int par_level, PAR_CSPRNG_STATE_T *const states) {
+ if (par_level == 1) {
+ csprng_release(&(states->state1));
+ } else if (par_level == 2) {
+ csprng_release_x2(&(states->state2));
+ } else if (par_level == 3) {
+ csprng_release_x3(&(states->state4));
+ } else if (par_level == 4) {
+ csprng_release_x4(&(states->state4));
+ }
+}
+
+/******************************************************************************/
+
+/* PQClean-edit: remove randombytes definition here to use PQClean randombytes */
+//static inline void randombytes(unsigned char * x, uint64_t xlen) ...
+
+/************************* HASH functions ********************************/
+
+/* Opaque algorithm agnostic hash call */
+static inline
+void hash(uint8_t digest[HASH_DIGEST_LENGTH],
+ const unsigned char *const m,
+ const uint64_t mlen) {
+ /* SHAKE with a 2*lambda bit digest is employed also for hashing */
+ CSPRNG_STATE_T csprng_state;
+ xof_shake_init(&csprng_state, SEED_LENGTH_BYTES * 8);
+ xof_shake_update(&csprng_state, m, mlen);
+ xof_shake_final(&csprng_state);
+ xof_shake_extract(&csprng_state, digest, HASH_DIGEST_LENGTH);
+ /* PQClean-edit: CSPRNG release context */
+ xof_shake_release(&csprng_state);
+}
+
+#define par_xof_input par_initialize_csprng
+#define par_xof_output par_csprng_randombytes
+#define par_xof_release par_csprng_release
+
+static inline
+void par_hash(
+ int par_level,
+ uint8_t digest_1[HASH_DIGEST_LENGTH],
+ uint8_t digest_2[HASH_DIGEST_LENGTH],
+ uint8_t digest_3[HASH_DIGEST_LENGTH],
+ uint8_t digest_4[HASH_DIGEST_LENGTH],
+ const unsigned char *const m_1,
+ const unsigned char *const m_2,
+ const unsigned char *const m_3,
+ const unsigned char *const m_4,
+ const uint64_t mlen) {
+ PAR_CSPRNG_STATE_T states;
+ par_xof_input(par_level, &states, m_1, m_2, m_3, m_4, mlen);
+ par_xof_output(par_level, &states, digest_1, digest_2, digest_3, digest_4, HASH_DIGEST_LENGTH);
+ par_xof_release(par_level, &states);
+}
+
+/********************** CSPRNG Sampling functions helpers ********************/
+
+static inline
+FQ_ELEM fq_star_rnd_state(CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_TO_REPRESENT(Q - 2) ) - 1;
+ FQ_ELEM rnd_value;
+ do {
+ csprng_randombytes((unsigned char *) &rnd_value,
+ sizeof(FQ_ELEM),
+ csprng_state);
+ rnd_value = mask & rnd_value;
+ } while (rnd_value > Q - 2);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(csprng_state);
+
+ return rnd_value + 1;
+} /* end fq_star_rnd_state */
+
+/***************** Specialized CSPRNGs for non binary domains *****************/
+
+/* CSPRNG sampling fixed weight strings */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_expand_digest_to_fixed_weight(uint8_t fixed_weight_string[T],
+ const uint8_t digest[HASH_DIGEST_LENGTH]);
+
+#define BITS_FOR_Q BITS_TO_REPRESENT(Q-1)
+#define BITS_FOR_Z BITS_TO_REPRESENT(Z-1)
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_FQ_VEC ((BITS_N_ZQ_CT_RNG - N*BITS_FOR_Q)* (BITS_FOR_Q-1))
+#define BUFSIZE_FQ_VEC (ROUND_UP(BITS_N_ZQ_CT_RNG+CORRECTION_FQ_VEC,8)/8)
+
+static inline
+void CSPRNG_fq_vec(FQ_ELEM res[N],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_FOR_Q) - 1;
+ /* NOTE: Current bit cost estimation technique underestimates the failures
+ * whenever they appear in a run; an upper bound on the bit-cost is considering
+ * the failures to be discarding the entire value, instead of a single bit.
+ * The following correction factor takes this into account */
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_N_ZQ_CT_RNG - N*BITS_FOR_Q)* (BITS_FOR_Q-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_N_ZQ_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_FQ_VEC];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right, shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_FQ_VEC, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+ while (placed < N) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ res[placed] = sub_buffer & mask;
+ if (res[placed] < Q) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Q;
+ bits_in_sub_buf -= BITS_FOR_Q;
+
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
+
+#define BITS_FOR_Q_M_ONE BITS_TO_REPRESENT(Q-2)
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_FQ_VEC_BETA ((BITS_BETA_ZQSTAR_CT_RNG - T*BITS_FOR_Q_M_ONE) * (BITS_FOR_Q_M_ONE-1))
+#define BUFSIZE_FQ_VEC_BETA (ROUND_UP(BITS_BETA_ZQSTAR_CT_RNG+CORRECTION_FQ_VEC_BETA,8)/8)
+
+static inline
+void CSPRNG_fq_vec_beta(FQ_ELEM res[T],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_FOR_Q_M_ONE) - 1;
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_BETA_ZQSTAR_CT_RNG - T*BITS_FOR_Q_M_ONE) * (BITS_FOR_Q_M_ONE-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_BETA_ZQSTAR_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_FQ_VEC_BETA];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right , shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_FQ_VEC_BETA, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+ while (placed < T) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ /* draw from 0 ... Q-2, then add 1*/
+ res[placed] = (sub_buffer & mask) + 1;
+ if (res[placed] < Q) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Q_M_ONE;
+ bits_in_sub_buf -= BITS_FOR_Q_M_ONE;
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_FQ_MAT ((BITS_V_CT_RNG - K*(N-K)*BITS_FOR_Q) * (BITS_FOR_Q-1))
+#define BUFSIZE_FQ_MAT (ROUND_UP(BITS_V_CT_RNG+CORRECTION_FQ_MAT,8)/8)
+
+static inline
+void CSPRNG_fq_mat(FQ_ELEM res[K][N - K],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_FOR_Q) - 1;
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_V_CT_RNG - K*(N-K)*BITS_FOR_Q) * (BITS_FOR_Q-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_V_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_FQ_MAT];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right , shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_FQ_MAT, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+
+ while (placed < K * (N - K)) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ *( (FQ_ELEM *)res + placed) = sub_buffer & mask;
+ if (*( (FQ_ELEM *)res + placed) < Q) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Q;
+ bits_in_sub_buf -= BITS_FOR_Q;
+
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_ZZ_VEC ((BITS_N_ZZ_CT_RNG - N*BITS_FOR_Z) * (BITS_FOR_Z-1))
+#define BUFSIZE_ZZ_VEC ROUND_UP(BITS_N_ZZ_CT_RNG+CORRECTION_ZZ_VEC,8)/8
+
+static inline
+void CSPRNG_zz_vec(FZ_ELEM res[N],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FZ_ELEM mask = ( (FZ_ELEM) 1 << BITS_FOR_Z) - 1;
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_N_ZZ_CT_RNG - N*BITS_FOR_Z) * (BITS_FOR_Z-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_N_ZZ_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_ZZ_VEC];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right , shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_ZZ_VEC, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+ while (placed < N) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ /* get */
+ res[placed] = sub_buffer & mask;
+ if (res[placed] < Z) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Z;
+ bits_in_sub_buf -= BITS_FOR_Z;
+
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/fq_arith.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/fq_arith.h
new file mode 100644
index 000000000..f30ac9702
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/fq_arith.h
@@ -0,0 +1,225 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include
+#include
+#include
+
+#include "architecture_detect.h"
+#include "csprng_hash.h"
+#include "parameters.h"
+#include "restr_arith.h"
+
+#define NUM_BITS_Q (BITS_TO_REPRESENT(Q))
+
+#define FQRED_SINGLE(x) (((x) & 0x7F) + ((x) >> 7))
+#define FQRED_DOUBLE(x) FQRED_SINGLE(FQRED_SINGLE(x))
+#define FQRED_OPPOSITE(x) ((x) ^ 0x7F)
+#define FQ_DOUBLE_ZERO_NORM(x) (((x) + (((x) + 1) >> 7)) & 0x7F)
+#define RESTR_TO_VAL(x) ( (FQ_ELEM) (RESTR_G_TABLE >> (8*(uint64_t)(x))) )
+
+/* in-place normalization of redundant zero representation for syndromes*/
+static inline
+void fq_dz_norm_synd(FQ_ELEM v[N - K]) {
+ for (int i = 0; i < N - K; i++) {
+ v[i] = FQ_DOUBLE_ZERO_NORM(v[i]);
+ }
+}
+
+static inline
+void fq_dz_norm(FQ_ELEM v[N]) {
+ for (int i = 0; i < N; i++) {
+ v[i] = FQ_DOUBLE_ZERO_NORM(v[i]);
+ }
+}
+
+/* Computes the product e*H of an n-element restricted vector by a (n-k)*n
+ * F_q H is in systematic form. Only the non systematic portion of H =[V I],
+ * V, is provided, transposed, hence linearized by columns so that syndrome
+ * computation is vectorizable. */
+/* Used by keygen */
+static
+void restr_vec_by_fq_matrix(FQ_ELEM res[N - K],
+ const FZ_ELEM e[N],
+ FQ_ELEM V_tr[K][N - K]) {
+ FQ_DOUBLEPREC res_dprec[N - K] = {0};
+ for (int i = 0; i < N - K; i++) {
+ res_dprec[i] = RESTR_TO_VAL(e[K + i]);
+ }
+ for (int i = 0; i < K; i++) {
+ for (int j = 0; j < N - K; j++) {
+ res_dprec[j] += FQRED_SINGLE(
+ (FQ_DOUBLEPREC) RESTR_TO_VAL(e[i]) *
+ (FQ_DOUBLEPREC) V_tr[i][j]);
+ if (i == Q - 1) {
+ res_dprec[j] = FQRED_SINGLE(res_dprec[j]);
+ }
+ }
+ }
+ /* Save result trimming to regular precision */
+ for (int i = 0; i < N - K; i++) {
+ res[i] = FQRED_SINGLE(res_dprec[i]);
+ }
+}
+
+/* Computes e * [I_k V]^T, V is already in transposed form
+ * since */
+static
+void fq_vec_by_fq_matrix(FQ_ELEM res[N - K],
+ const FQ_ELEM e[N],
+ FQ_DOUBLEPREC V_tr[K][ROUND_UP(N - K, EPI16_PER_REG)]) {
+
+ alignas(EPI8_PER_REG) FQ_DOUBLEPREC res_dprec[ROUND_UP(N - K, EPI16_PER_REG)] = {0};
+ for (int i = 0; i < N - K; i++) {
+ res_dprec[i] = e[K + i];
+ }
+ __m256i mred_mask = _mm256_set1_epi16 (0x007f);
+
+ for (int i = 0; i < K; i++) {
+ for (int j = 0; j < ROUND_UP(N - K, EPI16_PER_REG) / EPI16_PER_REG; j++) {
+ __m256i res_w = _mm256_load_si256(
+ (__m256i const *) &res_dprec[j * EPI16_PER_REG] );
+ __m256i e_coeff = _mm256_set1_epi16(e[i]);
+ __m256i V_tr_slice = _mm256_lddqu_si256(
+ (__m256i const *) &V_tr[i][j * EPI16_PER_REG] );
+ __m256i tmp = _mm256_mullo_epi16(e_coeff, V_tr_slice);
+ /* Vector Mersenne reduction */
+ __m256i tmp2 = _mm256_and_si256 (tmp, mred_mask);
+ tmp = _mm256_srli_epi16(tmp, 7);
+ tmp = _mm256_add_epi16(tmp, tmp2);
+ res_w = _mm256_add_epi16(res_w, tmp);
+ /* store back*/
+ _mm256_store_si256 ((__m256i *) &res_dprec[j * EPI16_PER_REG], res_w);
+ }
+ }
+ /* Save result trimming to regular precision */
+ for (int i = 0; i < N - K; i++) {
+ res[i] = FQRED_DOUBLE(res_dprec[i]);
+ }
+}
+
+static inline
+void fq_vec_by_fq_vec_pointwise(FQ_ELEM res[N],
+ const FQ_ELEM in1[N],
+ const FQ_ELEM in2[N]) {
+ for (int i = 0; i < N; i++) {
+ res[i] = FQRED_SINGLE( (FQ_DOUBLEPREC) in1[i] *
+ (FQ_DOUBLEPREC) in2[i] );
+ }
+}
+
+static inline
+void restr_by_fq_vec_pointwise(FQ_ELEM res[N],
+ const FZ_ELEM in1[N],
+ const FQ_ELEM in2[N]) {
+ for (int i = 0; i < N; i++) {
+ res[i] = FQRED_SINGLE( (FQ_DOUBLEPREC) RESTR_TO_VAL(in1[i]) *
+ (FQ_DOUBLEPREC) in2[i]);
+ }
+}
+
+/* e*beta + u_tilde*/
+static inline
+void fq_vec_by_restr_vec_scaled(FQ_ELEM res[N],
+ const FZ_ELEM e[N],
+ const FQ_ELEM beta,
+ const FQ_ELEM u_tilde[N]) {
+
+ alignas(EPI8_PER_REG) FZ_ELEM e_align[ROUND_UP(N, EPI8_PER_REG)];
+ alignas(EPI8_PER_REG) FQ_ELEM utilde_align[ROUND_UP(N, EPI8_PER_REG)];
+ alignas(EPI8_PER_REG) FQ_ELEM res_align[ROUND_UP(N, EPI8_PER_REG)];
+ __m256i mred_mask = _mm256_set1_epi16 ((uint16_t)0x007f);
+ __m256i dense_mred_mask = _mm256_set1_epi8 ((uint8_t)0x7f);
+ __m256i dense_neg_mred_mask = _mm256_set1_epi8 ((uint8_t)0x80);
+ memcpy(e_align, e, N);
+ memcpy(utilde_align, u_tilde, N);
+
+ /* set a register with beta, EPI16_PER_REG times */
+ __m256i beta_comb = _mm256_set1_epi16 ((uint16_t) beta);
+
+ /* Since the single-cycle shuffle acts only on 128b lanes separately,
+ * prepare two pairs of tables, with alternating scattered elements, to be
+ * broadcast-multiplied. Results are then reduced, and byte packed again
+ * to allow the use of the shuffle instruction */
+ __m256i LUT_sparse = _mm256_set_epi16 (0x0001, 0x0020, 0x0008, 0x0002,
+ 0x0040, 0x0010, 0x0004, 0x0001,
+ 0x0001, 0x0020, 0x0008, 0x0002,
+ 0x0040, 0x0010, 0x0004, 0x0001);
+
+ /* comb-multiply the lookup table made of a single register obtaining
+ * pre-scaled values */
+ LUT_sparse = _mm256_mullo_epi16(LUT_sparse, beta_comb);
+ /* Vector Mersenne reduction */
+ __m256i tmp = _mm256_and_si256 (LUT_sparse, mred_mask);
+ LUT_sparse = _mm256_srli_epi16(LUT_sparse, 7);
+ LUT_sparse = _mm256_add_epi16(tmp, LUT_sparse);
+ /*semantics from the manual call for a *byte amount* in _mm256_srli_si256*/
+ tmp = _mm256_srli_si256(LUT_sparse, 7);
+ LUT_sparse = _mm256_or_si256(LUT_sparse, tmp);
+
+ /* Convert restricted to rescaled values by batch exponentiating them
+ * via shuffle: "shuffling" the table according to the restricted values
+ * yields beta-multiplied elements of F_q*/
+ for (int i = 0; i < ROUND_UP(N, EPI8_PER_REG) / EPI8_PER_REG; i++ ) {
+ __m256i e_word = _mm256_load_si256( (__m256i const *) &e_align[i * EPI8_PER_REG]);
+ e_word = _mm256_shuffle_epi8(LUT_sparse, e_word);
+ /* add to u tilde */
+ __m256i utilde_word = _mm256_load_si256( (__m256i const *) &utilde_align[i * EPI8_PER_REG]);
+ __m256i res_word = _mm256_add_epi8(e_word, utilde_word);
+ /* reduce, knowing that a single out bit is the max overflow */
+ tmp = _mm256_and_si256 (res_word, dense_mred_mask);
+ /* no _mm256_srli_epi8 available, cope with the lack hand-clearing
+ * all other bits before shifting */
+ res_word = _mm256_srli_epi16(
+ _mm256_and_si256(res_word, dense_neg_mred_mask),
+ 7);
+ res_word = _mm256_add_epi8(res_word, tmp);
+ _mm256_store_si256 ((__m256i *) &res_align[i * EPI8_PER_REG], res_word);
+
+ }
+ memcpy(res, res_align, N);
+}
+
+static inline
+void fq_synd_minus_fq_vec_scaled(FQ_ELEM res[N - K],
+ const FQ_ELEM synd[N - K],
+ const FQ_ELEM beta,
+ const FQ_ELEM s[N - K]) {
+ for (int j = 0; j < N - K; j++) {
+ FQ_ELEM tmp = FQRED_SINGLE( (FQ_DOUBLEPREC) s[j] * (FQ_DOUBLEPREC) beta);
+ tmp = FQ_DOUBLE_ZERO_NORM(tmp);
+ res[j] = FQRED_SINGLE( (FQ_DOUBLEPREC) synd[j] + FQRED_OPPOSITE(tmp) );
+ }
+}
+
+static inline
+void convert_restr_vec_to_fq(FQ_ELEM res[N],
+ const FZ_ELEM in[N]) {
+ for (int j = 0; j < N; j++) {
+ res[j] = RESTR_TO_VAL(in[j]);
+ }
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/merkle.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/merkle.c
new file mode 100644
index 000000000..70d2bef68
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/merkle.c
@@ -0,0 +1,399 @@
+/*
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (May 2023)
+ *
+ * @author: Patrick Karl
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+#include
+
+#include "merkle.h"
+
+#define LEAVES_FULL_TREE(L) ( (1UL << LOG2(L) ) )
+#define LEAVES_HALF_TREE(L) ( (LEAVES_FULL_TREE(L) >> 1) )
+
+#define PARENT(i) ( ((i)%2) ? (((i)-1)/2) : (((i)-2)/2) )
+#define RIGHT_CHILD(i) ( (2*(i)+2) )
+#define LEFT_CHILD(i) ( (2*(i)+1) )
+#define SIBLING(i) ( ((i)%2) ? (i)+1 : (i)-1 )
+
+#define RL(i) ((i)==1 ? r_node : l_node)
+#define OFFSET(i) ( (i)*HASH_DIGEST_LENGTH )
+
+#define CHALLENGE_PROOF_VALUE 0
+#define INVALID_MERKLE_NODE 0
+#define VALID_MERKLE_NODE 1
+
+#define NOT_COMPUTED 0
+#define COMPUTED 1
+
+/* maximum number of parallel executions of the hash function */
+#define PAR_DEGREE 4
+
+/*
+ * setup_tree()
+ *
+ * uint16_t layer_offset[LOG2(T)+1] : Stores one offset per layer for layer change.
+ * Required for the computation of PARENT and CHILD nodes.
+ * uint16_t nodes_per_layer[LOG2(T)+1] : Stores the numbers of nodes used in the truncated Merkle tree.
+ */
+static
+void setup_tree(uint16_t layer_offsets[LOG2(T) + 1],
+ uint16_t nodes_per_layer[LOG2(T) + 1]) {
+ uint32_t depth, layer;
+ uint32_t r_leaves;
+ int subtree_found;
+
+ /* Initialize array with full node counts */
+ for (size_t i = 0; i < LOG2(T) + 1; i++) {
+ layer_offsets[i] = (1UL << i);
+ }
+
+ /* Count root node */
+ layer = 0;
+ layer_offsets[layer] -= 1;
+
+ /* Count left tree nodes (always full) */
+ for (size_t i = 1; i < LOG2(T) + 1; i++) {
+ layer_offsets[i] -= (1UL << (i - 1));
+ }
+
+ /* Check every full subtree on right side and subtract missing nodes */
+ r_leaves = T - (1UL << (LOG2(T) - 1));
+ layer = 1;
+ while (r_leaves > 0) {
+ depth = 0;
+ subtree_found = 0;
+ while ( !subtree_found ) {
+ if (r_leaves <= (1UL << depth)) {
+ for (int i = depth; i > 0; i--) {
+ layer_offsets[layer + i] -= (1UL << (i - 1));
+ }
+ r_leaves -= LEAVES_HALF_TREE(r_leaves);
+ layer_offsets[layer] -= 1;
+ layer++;
+ subtree_found = 1;
+ } else {
+ depth++;
+ }
+ }
+ }
+
+ /* For the offset, subtract all missing nodes from previous layers from current layer */
+ for (int i = LOG2(T); i >= 0; i--) {
+ nodes_per_layer[i] = (1UL << i) - layer_offsets[i];
+ for (int j = i - 1; j >= 0; j--) {
+ layer_offsets[i] -= layer_offsets[j];
+ }
+ layer_offsets[i] >>= 1;
+ }
+}
+
+/*
+ * get_leaf_indices() is quite similar to setup_tree(), however requires the
+ * offset values to compute the correct indices.
+ *
+ * uint16_t merkle_leaf_indices[T] : Stores the indices in the truncated tree
+ * where the leaves are placed.
+ * uint16_t layer_offsets[LOG2(T)+1] : Same as above.
+ */
+static
+void get_leaf_indices(uint16_t merkle_leaf_indices[T],
+ const uint16_t layer_offsets[LOG2(T) + 1]) {
+ uint32_t r_leaves;
+ uint32_t idx_ctr = 0;
+
+ /* r_node: current root node of next subtree, will always be right-child of previous root */
+ /* l_node: traverses from current root node to left-childs until depth of subtree is found */
+ uint32_t r_node, l_node;
+ uint32_t layer, depth, subtree_found;
+
+ /* If tree is already balanced, simply copy leaves to corresponding position */
+ if (T == (1UL << LOG2(T))) {
+ for (size_t i = 0; i < T; i++) {
+ merkle_leaf_indices[i] = T - 1 + i;
+ }
+ return;
+ }
+
+ /* Create (un-) balanced Merkle tree */
+ r_leaves = T;
+ depth = 0;
+ layer = 0;
+ r_node = 0;
+ l_node = LEFT_CHILD(r_node) - 2 * layer_offsets[layer + depth];
+ while (r_leaves > 0) {
+ depth = 1;
+ subtree_found = 0;
+ /* Start from the current root node r_node until the size of a full left-subtree is found. */
+ /* If only one leaf is remaining, put it to current root-node, macro RL() is used to decide that. */
+ while ( !subtree_found ) {
+ if (r_leaves <= (1UL << depth)) {
+ for (size_t j = 0; j < LEAVES_HALF_TREE(r_leaves); j++) {
+ merkle_leaf_indices[idx_ctr++] = RL(r_leaves) + j;
+ }
+ r_node = RIGHT_CHILD(r_node) - 2 * layer_offsets[layer];
+ l_node = LEFT_CHILD(r_node) - 2 * layer_offsets[layer];
+ layer++;
+ r_leaves -= LEAVES_HALF_TREE(r_leaves);
+ subtree_found = 1;
+ } else {
+ l_node = LEFT_CHILD(l_node) - 2 * layer_offsets[layer + depth];
+ depth++;
+ }
+ }
+ }
+}
+
+/* PQCLEAN_CROSSRSDP128BALANCED_AVX2_generate_merkle_tree()
+ *
+ * unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH] :
+ * stores the hashes of the associated tree nodes.
+ * const unsigned char commitments[T][HASH_DIGEST_LENGTH] : Contains the
+ * hashed commitments that build the tree.
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generate_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE *
+ HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH]) {
+ size_t i;
+ uint32_t node_ctr, parent_layer;
+
+ uint16_t merkle_leaf_indices[T];
+ uint16_t layer_offsets[LOG2(T) + 1];
+ uint16_t nodes_per_layer[LOG2(T) + 1];
+
+ /* Setup the tree to get offsets for the computation of PARENT/CHILD nodes, as well as the number of nodes per layer */
+ /* Move leafs in correct positions of the unbalanced Merkle tree */
+ setup_tree(layer_offsets, nodes_per_layer);
+ get_leaf_indices(merkle_leaf_indices, layer_offsets);
+
+ /* Place commitments on the leaves indicated by merkle_leaf_indices */
+ for (i = 0; i < T; i++) {
+ memcpy(merkle_tree + merkle_leaf_indices[i]*HASH_DIGEST_LENGTH,
+ commitments + i,
+ HASH_DIGEST_LENGTH);
+ }
+
+ /* enqueue the calls to hash */
+ int to_hash = 0;
+ int out_pos_queue[4] = {0};
+ int in_pos_queue[4] = {0};
+
+ /* create the hash tree starting from the leaves */
+ node_ctr = 0;
+ parent_layer = LOG2(T) - 1;
+ for (i = NUM_NODES_MERKLE_TREE - 1; i > 0; i -= 2) {
+ /* save the position of the hash inputs and outputs */
+ to_hash++;
+ out_pos_queue[to_hash - 1] = OFFSET(PARENT(i) + layer_offsets[parent_layer]);
+ in_pos_queue[to_hash - 1] = OFFSET(SIBLING(i));
+ /* go up to the next tree level */
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ /* hash in batches of 4 (or less when changing tree level) */
+ if (to_hash == 4 || node_ctr == 0) {
+ par_hash(
+ to_hash,
+ merkle_tree + out_pos_queue[0],
+ merkle_tree + out_pos_queue[1],
+ merkle_tree + out_pos_queue[2],
+ merkle_tree + out_pos_queue[3],
+ merkle_tree + in_pos_queue[0],
+ merkle_tree + in_pos_queue[1],
+ merkle_tree + in_pos_queue[2],
+ merkle_tree + in_pos_queue[3],
+ 2 * HASH_DIGEST_LENGTH);
+ to_hash = 0;
+ }
+ }
+}
+
+/* PQCLEAN_CROSSRSDP128BALANCED_AVX2_generate_merkle_proof()
+ *
+ * uint16_t merkle_proof_indices[TREE_NODES_TO_STORE] : stores the sorted indices required for the proof.
+ * uint16_t merkle_proof_len : Actual length of the proof. Can vary depending on the challenge.
+ * const unsigned char challenge : Challenge that indicated which nodes will be recomputed by the verifier.
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generate_merkle_proof(uint16_t merkle_proof_indices[TREE_NODES_TO_STORE],
+ uint16_t *merkle_proof_len,
+ const unsigned char challenge[T]) {
+ unsigned char flag_tree[NUM_NODES_MERKLE_TREE] = {NOT_COMPUTED};
+ uint32_t node_ctr, parent_layer;
+ size_t i;
+
+ uint16_t layer_offsets[LOG2(T) + 1];
+ uint16_t nodes_per_layer[LOG2(T) + 1];
+ uint16_t merkle_leaf_indices[T];
+
+ /* Setup the tree to get offsets for the computation of PARENT/CHILD nodes, as well as the number of nodes per layer */
+ setup_tree(layer_offsets, nodes_per_layer);
+ get_leaf_indices(merkle_leaf_indices, layer_offsets);
+
+ /* Use challenges to mark nodes of path tree */
+ for (size_t j = 0; j < T; j++) {
+ if (challenge[j] == CHALLENGE_PROOF_VALUE) {
+ flag_tree[merkle_leaf_indices[j]] = COMPUTED;
+ }
+ }
+
+ /* Loop over all nodes, starting at the leaves */
+ /* If at least one sibling is marked as COMPUTED, also mark the PARENT as such */
+ /* Only add sibling of COMPUTED sibling as proof node if not both of them are marked as COMPUTED. */
+ node_ctr = 0;
+ parent_layer = LOG2(T) - 1;
+ *merkle_proof_len = 0;
+ for (i = NUM_NODES_MERKLE_TREE - 1; i > 0; i -= 2) {
+
+ flag_tree[PARENT(i) + layer_offsets[parent_layer]] = (flag_tree[i] == COMPUTED) || (flag_tree[SIBLING(i)] == COMPUTED);
+
+ /* Add left sibling only if left one was computed */
+ if ( (flag_tree[i] == COMPUTED) && (flag_tree[SIBLING(i)] == NOT_COMPUTED) ) {
+ merkle_proof_indices[(*merkle_proof_len)++] = SIBLING(i);
+ }
+
+ /* Add right sibling only right was computed */
+ if ( (flag_tree[i] == NOT_COMPUTED) && (flag_tree[SIBLING(i)] == COMPUTED) ) {
+ merkle_proof_indices[(*merkle_proof_len)++] = i;
+ }
+
+ /* Due to the unbalenced structure we got to keep track of the nodes per layer processed */
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ }
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_rebuild_merkle_tree()
+ *
+ * unsigned char merkle_tree[NUM_NODES_MERKLE_TREE*HASH_DIGEST_LENGTH] : Stores the Hashes of the recomputed Merkle tree.
+ * const unsigned char merkle_proof[TREE_NODES_TO_STORE] : Merkle proof containing the nodes required for recomputation.
+ * const unsigned char commitments[T][HASH_DIGEST_LENGTH] : Stores the commitments.
+ * const unsigned char challenge[T] : Challenge vector to indicate the computed commitments.
+ */
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_rebuild_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ const unsigned char merkle_proof[TREE_NODES_TO_STORE * HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH],
+ const unsigned char challenge[T]) {
+ uint16_t flag_tree_valid[NUM_NODES_MERKLE_TREE] = {INVALID_MERKLE_NODE};
+
+ uint16_t merkle_leaf_indices[T];
+ uint16_t layer_offsets[LOG2(T) + 1];
+ uint16_t nodes_per_layer[LOG2(T) + 1];
+
+ uint16_t ctr;
+ uint32_t node_ctr, parent_layer;
+ size_t i;
+
+ /* Move leafs in correct positions of binary merkle tree */
+ /* Setup the tree again, computing the offsets and from that, the leaf indices */
+ setup_tree(layer_offsets, nodes_per_layer);
+ get_leaf_indices(merkle_leaf_indices, layer_offsets);
+
+ /* Copy the commitments to the positions indicated by the challenge */
+ for (i = 0; i < T; i++) {
+ if (challenge[i] == CHALLENGE_PROOF_VALUE) {
+ flag_tree_valid[merkle_leaf_indices[i]] = VALID_MERKLE_NODE;
+ memcpy(merkle_tree + merkle_leaf_indices[i]*HASH_DIGEST_LENGTH, commitments + i, HASH_DIGEST_LENGTH);
+ }
+ }
+
+ /* enqueue the calls to hash */
+ int to_hash = 0;
+ int out_pos_queue[4] = {0};
+ int in_pos_queue[4] = {0};
+
+ /* Create hash tree by hashing valid leaf nodes */
+ ctr = 0;
+ node_ctr = 0;
+ parent_layer = LOG2(T) - 1;
+ for (i = NUM_NODES_MERKLE_TREE - 1; i > 0; i -= 2) {
+
+ /* Both siblings are unused, but it must be kept track of the node and layer counter to chose the right offsets */
+ if (flag_tree_valid[i] == INVALID_MERKLE_NODE && flag_tree_valid[SIBLING(i)] == INVALID_MERKLE_NODE) {
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ }
+
+ else {
+ /* at least one of the siblings is valid: there is a hash to compute */
+ to_hash++;
+ /* save the position of the hash inputs and outputs */
+ out_pos_queue[to_hash - 1] = OFFSET(PARENT(i) + layer_offsets[parent_layer]);
+ in_pos_queue[to_hash - 1] = OFFSET(SIBLING(i));
+
+ /* if the right sibling is invalid, copy it from the merkle proof */
+ if (flag_tree_valid[i] == INVALID_MERKLE_NODE) {
+ memcpy(
+ merkle_tree + OFFSET(i),
+ merkle_proof + OFFSET(ctr),
+ HASH_DIGEST_LENGTH);
+ ctr++;
+ }
+
+ /* if the left sibling is invalid, copy it from the merkle proof */
+ if (flag_tree_valid[SIBLING(i)] == INVALID_MERKLE_NODE) {
+ memcpy(
+ merkle_tree + OFFSET(SIBLING(i)),
+ merkle_proof + OFFSET(ctr),
+ HASH_DIGEST_LENGTH);
+ ctr++;
+ }
+
+ /* set the parent node as valid */
+ flag_tree_valid[PARENT(i) + layer_offsets[parent_layer]] = VALID_MERKLE_NODE;
+
+ /* go up to the next tree level */
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ }
+
+ /* hash in batches of 4 (or less when changing tree level) */
+ if (to_hash == 4 || node_ctr == 0) {
+ par_hash(
+ to_hash,
+ merkle_tree + out_pos_queue[0],
+ merkle_tree + out_pos_queue[1],
+ merkle_tree + out_pos_queue[2],
+ merkle_tree + out_pos_queue[3],
+ merkle_tree + in_pos_queue[0],
+ merkle_tree + in_pos_queue[1],
+ merkle_tree + in_pos_queue[2],
+ merkle_tree + in_pos_queue[3],
+ 2 * HASH_DIGEST_LENGTH);
+ to_hash = 0;
+ }
+ }
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/merkle.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/merkle.h
new file mode 100644
index 000000000..d550153e2
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/merkle.h
@@ -0,0 +1,41 @@
+/*
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (May 2023)
+ *
+ * @author: Patrick Karl
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "csprng_hash.h"
+#include "parameters.h"
+
+/***********************************************************************************************/
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generate_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH]);
+
+/***********************************************************************************************/
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generate_merkle_proof(uint16_t merkle_proof_indices[TREE_NODES_TO_STORE],
+ uint16_t *merkle_proof_len,
+ const unsigned char challenge[T]);
+
+/***********************************************************************************************/
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_rebuild_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ const unsigned char merkle_proof[TREE_NODES_TO_STORE * HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH],
+ const unsigned char challenge[T]);
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/merkle_tree.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/merkle_tree.h
new file mode 100644
index 000000000..dff03e070
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/merkle_tree.h
@@ -0,0 +1,83 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author: Patrick Karl
+ * @author Gerardo Pelosi
+ *
+ * Authors listed in lexicographic order.
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "csprng_hash.h"
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_merkle_tree_root_compute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ uint8_t leaves[T][HASH_DIGEST_LENGTH]);
+uint16_t PQCLEAN_CROSSRSDP128BALANCED_AVX2_merkle_tree_proof_compute(uint8_t mtp[HASH_DIGEST_LENGTH * TREE_NODES_TO_STORE],
+ const uint8_t tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ const uint8_t leaves_to_reveal[T]);
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_merkle_tree_root_recompute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t recomputed_leaves[T][HASH_DIGEST_LENGTH],
+ const uint8_t mtp[HASH_DIGEST_LENGTH * TREE_NODES_TO_STORE],
+ const uint8_t leaves_to_reveal[T]);
+
+#include "merkle.h"
+/* Stub of the interface to Merkle tree root computer from all leaves */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_merkle_tree_root_compute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ /* input, although mutable in caller, having as const is non
+ * tolerated in strict ISO C */
+ uint8_t leaves[T][HASH_DIGEST_LENGTH]) {
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_generate_merkle_tree(tree, leaves);
+ /* Root is at first position of the tree */
+ memcpy(root, tree, HASH_DIGEST_LENGTH);
+}
+
+/* Stub interface to the function computing the Merkle tree proof, storing it
+ * in the signature. Returns the number of digests in the merkle tree proof */
+uint16_t PQCLEAN_CROSSRSDP128BALANCED_AVX2_merkle_tree_proof_compute(uint8_t mtp[HASH_DIGEST_LENGTH * TREE_NODES_TO_STORE],
+ const uint8_t tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ const uint8_t leaves_to_reveal[T]) {
+ uint16_t mtp_len;
+ uint16_t merkle_proof_indices[TREE_NODES_TO_STORE];
+
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_generate_merkle_proof(merkle_proof_indices, &mtp_len, leaves_to_reveal);
+
+ for (size_t i = 0; i < mtp_len; i++) {
+ memcpy(mtp + i * HASH_DIGEST_LENGTH, tree + merkle_proof_indices[i]*HASH_DIGEST_LENGTH,
+ HASH_DIGEST_LENGTH);
+ }
+ return mtp_len;
+}
+
+/* stub of the interface to Merkle tree recomputation given the proof and
+ * the computed leaves */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_merkle_tree_root_recompute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t recomputed_leaves[T][HASH_DIGEST_LENGTH],
+ const uint8_t mtp[HASH_DIGEST_LENGTH * TREE_NODES_TO_STORE],
+ const uint8_t leaves_to_reveal[T]) {
+
+ unsigned char tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH];
+
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_rebuild_merkle_tree(tree, mtp, recomputed_leaves, leaves_to_reveal);
+ memcpy(root, tree, HASH_DIGEST_LENGTH);
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/pack_unpack.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/pack_unpack.c
new file mode 100644
index 000000000..7479c467c
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/pack_unpack.c
@@ -0,0 +1,618 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Jonas Schupp
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include
+#include
+
+#include "pack_unpack.h"
+
+/*Implementation of packing of 1 to 16 bits value vectors in 8 bit vectors,
+ * generic inputs from 1 to 16 bit possible*/
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_vec()
+ *
+ * uint8_t out[DENSELY_PACKED_FQ_VEC_SIZE] : FQ packed in bytes
+ * const FQ_ELEM in[N] : FQ Vec input, to be packed
+ *
+ * This function handles the packing of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_vec(uint8_t out[DENSELY_PACKED_FQ_VEC_SIZE],
+ const FQ_ELEM in[N]) {
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_pack_fq(out, in, DENSELY_PACKED_FQ_VEC_SIZE, N);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_syn()
+ *
+ * uint8_t out[DENSELY_PACKED_FQ_SYN_SIZE] : FQ packed in bytes
+ * const FQ_ELEM in[N-K] : FQ Vec input, to be packed
+ *
+ * This function handles the packing of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_syn(uint8_t out[DENSELY_PACKED_FQ_SYN_SIZE],
+ const FQ_ELEM in[N - K]) {
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_pack_fq(out, in, DENSELY_PACKED_FQ_SYN_SIZE, N - K);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fz_vec()
+ *
+ * uint8_t out[DENSELY_PACKED_FZ_VEC_SIZE] : FQ packed in bytes
+ * const FZ_ELEM in[N] : FQ Vec input, to be packed
+ *
+ * This function handles the packing of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fz_vec(uint8_t out[DENSELY_PACKED_FZ_VEC_SIZE],
+ const FZ_ELEM in[N]) {
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_pack_fz(out, in, DENSELY_PACKED_FZ_VEC_SIZE, N);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fz_rsdp_g_vec()
+ *
+ * uint8_t out[DENSELY_PACKED_FZ_RSDP_G_VEC_SIZE] : Zz packed in bytes
+ * const FZ_ELEM in[M] : Zz Vec input, to be packed
+ *
+ * This function handles the packing of the add. rdsp(g) vector in Zz
+ */
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_pack_fq()
+ *
+ * uint8_t *out : FQ packed in bytes
+ * const FQ_ELEM *in : FQ Vec input, to be packed
+ * size_t outlen : Length of out
+ * size_t in : Length of in
+ *
+ * This function handles the packing of an vector of el. in FQ of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_pack_fq(uint8_t *out, const FQ_ELEM *in,
+ const size_t outlen, const size_t inlen) {
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen / 8; i++) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] |= (in[i * 8 + 4] << 5) | (in[i * 8 + 5] >> 2);
+ out[i * 7 + 5] |= (in[i * 8 + 5] << 6) | (in[i * 8 + 6] >> 1);
+ out[i * 7 + 6] |= (in[i * 8 + 6] << 7) | (in[i * 8 + 7]);
+ }
+ const uint8_t n_remainder = inlen % 8;
+ if (n_remainder == 1) {
+ out[i * 7] = (in[i * 8] << 1);
+ } else if (n_remainder == 2) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] = (in[i * 8 + 1] << 2);
+ } else if (n_remainder == 3) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] = (in[i * 8 + 2] << 3);
+ } else if (n_remainder == 4) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4);
+ } else if (n_remainder == 5) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] = (in[i * 8 + 4] << 5);
+ } else if (n_remainder == 6) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] |= (in[i * 8 + 4] << 5) | (in[i * 8 + 5] >> 2);
+ out[i * 7 + 5] = (in[i * 8 + 5] << 6);
+ } else if (n_remainder == 7) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] |= (in[i * 8 + 4] << 5) | (in[i * 8 + 5] >> 2);
+ out[i * 7 + 5] |= (in[i * 8 + 5] << 6) | (in[i * 8 + 6] >> 1);
+ out[i * 7 + 6] |= (in[i * 8 + 6] << 7);
+ }
+
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_pack_fz()
+ *
+ * uint8_t *out : Zz packed in bytes
+ * const FZ_ELEM *in : Zz Vec input, to be packed
+ * size_t outlen : Length of out
+ * size_t in : Length of in
+ *
+ * This function handles the packing of an vector of el. in Zz of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_pack_fz(uint8_t *out, const FZ_ELEM *in, const size_t outlen, const size_t inlen) {
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen / 8; i++) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ out[i * 3 + 1] |= (in[i * 8 + 5] >> 2);
+ out[i * 3 + 2] = (in[i * 8 + 5] << 6);
+ out[i * 3 + 2] |= (in[i * 8 + 6] << 3);
+ out[i * 3 + 2] |= (in[i * 8 + 7]);
+ }
+ const uint8_t n_remainder = inlen % 8;
+ if (n_remainder == 1) {
+ out[i * 3] = (in[i * 8] << 5);
+ } else if (n_remainder == 2) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ } else if (n_remainder == 3) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ } else if (n_remainder == 4) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ } else if (n_remainder == 5) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ } else if (n_remainder == 6) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ out[i * 3 + 1] |= (in[i * 8 + 5] >> 2);
+ out[i * 3 + 2] = (in[i * 8 + 5] << 6);
+ } else if (n_remainder == 7) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ out[i * 3 + 1] |= (in[i * 8 + 5] >> 2);
+ out[i * 3 + 2] = (in[i * 8 + 5] << 6);
+ out[i * 3 + 2] |= (in[i * 8 + 6] << 3);
+ }
+
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fq_vec()
+ *
+ * FQ_ELEM out[N] : FQ Vec output
+ * const uint8_t in[DENSELY_PACKED_FQ_VEC_SIZE] : FQ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fq_vec(FQ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FQ_VEC_SIZE]) {
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_unpack_fq(out, in, N, DENSELY_PACKED_FQ_VEC_SIZE);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fq_syn()
+ *
+ * FQ_ELEM out[N] : FQ Vec output
+ * const uint8_t in[DENSELY_PACKED_FQ_SYN_SIZE] : FQ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fq_syn(FQ_ELEM out[N - K],
+ const uint8_t in[DENSELY_PACKED_FQ_SYN_SIZE]) {
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_unpack_fq(out, in, N - K, DENSELY_PACKED_FQ_SYN_SIZE);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fz_vec()
+ *
+ * FZ_ELEM out[N] : FQ Vec output
+ * const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE] : FQ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fz_vec(FZ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE]) {
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_unpack_fz(out, in, N);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fz_rsdp_g_vec()
+ *
+ * FZ_ELEM out[M] : FZ Vec output
+ * const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE] : FZ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_unpack_fq()
+ *
+ * FQ_ELEM *out : FQ output, unpacked
+ * const uint8_t *in : FQ Vec input, packed in bytes
+ * size_t outlen : Length of out
+ * size_t in : Length of in
+ *
+ * This function unpacks an vector of el. in FQ of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_unpack_fq(FQ_ELEM *out, const uint8_t *in,
+ size_t outlen, size_t inlen) {
+
+ /* PQClean-edit: unused parameter */
+ (void)inlen;
+
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen / 8; i++) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ out[i * 8 + 5] = ((in[i * 7 + 4] << 2) & 0x7F);
+ out[i * 8 + 5] |= (in[i * 7 + 5] >> 6);
+ out[i * 8 + 6] = ((in[i * 7 + 5] << 1) & 0x7F);
+ out[i * 8 + 6] |= (in[i * 7 + 6] >> 7);
+ out[i * 8 + 7] = (in[i * 7 + 6] & 0x7F);
+ }
+ const uint8_t n_remainder = outlen % 8;
+ if (n_remainder == 1) {
+ out[i * 8] = (in[i * 7] >> 1);
+ } else if (n_remainder == 2) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ } else if (n_remainder == 3) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ } else if (n_remainder == 4) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ } else if (n_remainder == 5) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ } else if (n_remainder == 6) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ out[i * 8 + 5] = ((in[i * 7 + 4] << 2) & 0x7F);
+ out[i * 8 + 5] |= (in[i * 7 + 5] >> 6);
+ } else if (n_remainder == 7) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ out[i * 8 + 5] = ((in[i * 7 + 4] << 2) & 0x7F);
+ out[i * 8 + 5] |= (in[i * 7 + 5] >> 6);
+ out[i * 8 + 6] = ((in[i * 7 + 5] << 1) & 0x7F);
+ out[i * 8 + 6] |= (in[i * 7 + 6] >> 7);
+ }
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_unpack_fz()
+ *
+ * FZ_ELEM *out : Zz output, unpacked
+ * const uint8_t *in : Zz Vec input, packed in bytes
+ * size_t outlen : Length of out
+ *
+ * This function unpacks an vector of el. in Zz of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_unpack_fz(FZ_ELEM *out, const uint8_t *in,
+ size_t outlen) {
+
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen / 8; i++) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ out[i * 8 + 5] = ((in[i * 3 + 1] << 2) & 0x7);
+ out[i * 8 + 5] |= ((in[i * 3 + 2] >> 6) & 0x7);
+ out[i * 8 + 6] = ((in[i * 3 + 2] >> 3) & 0x7);
+ out[i * 8 + 7] = ((in[i * 3 + 2]) & 0x7);
+ }
+ const uint8_t n_remainder = outlen % 8;
+ if (n_remainder == 1) {
+ out[i * 8] = (in[i * 3] >> 5);
+ }
+ if (n_remainder == 2) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ }
+ if (n_remainder == 3) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ }
+ if (n_remainder == 4) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ }
+ if (n_remainder == 5) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ }
+ if (n_remainder == 6) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ out[i * 8 + 5] = ((in[i * 3 + 1] << 2) & 0x7);
+ out[i * 8 + 5] |= ((in[i * 3 + 2] >> 6) & 0x7);
+ }
+ if (n_remainder == 7) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ out[i * 8 + 5] = ((in[i * 3 + 1] << 2) & 0x7);
+ out[i * 8 + 5] |= ((in[i * 3 + 2] >> 6) & 0x7);
+ out[i * 8 + 6] = ((in[i * 3 + 2] >> 3) & 0x7);
+ }
+
+}
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_uint16_t_pack(uint8_t *out, const uint16_t *in,
+ size_t outlen, size_t inlen, uint8_t btr) {
+ size_t i;
+ size_t in_i = 0;
+ uint8_t left, right;
+ uint8_t skip = 0;
+ if (btr <= 8) {
+ left = 8 - btr;
+ right = 0;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen; i++) {
+ while (right < 8 && in_i < inlen) {
+ out[i] |= (in[in_i] << (left)) >> right;
+ right += 8 - left;
+ left = 8 - btr;
+ in_i++;
+ }
+ if (right != 8) {
+ in_i--;
+ left = 2 * 8 - right;
+ } else {
+ left = 8 - btr;
+ }
+ right = 0;
+ }
+ } else if (btr == 8) {
+ for (i = 0; i < outlen; i++) {
+ out[i] = in[i];
+ }
+ } else if ((btr > 8) && (btr <= 16)) {
+ left = 0;
+ right = btr - 8;
+ skip = 0;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen; i++) {
+ skip = 0;
+ while (skip == 0 && in_i < inlen) {
+ out[i] |= (uint8_t)((in[in_i] << left) >> right);
+ // First case: left == 0,
+ // i.e.: the current value covers the LSBs of the packed value
+ if (left == 0) {
+ skip = 1;
+ //Case 0: This value was complete,
+ //i.e. a new one needs to be started
+ if (right == 0) {
+ in_i++;
+ left = 0;
+ right = btr - 8;
+ }
+ //Case 1: These were not the LSBs of this value,
+ //i.e. its LSBs need to be stored in the next block
+ else if (right <= 8) {
+ left = 8 - right;
+ right = 0;
+ } else {
+ right -= 8;
+ }
+
+ }
+ // Second case: right == 0 and left > 0,
+ // i.e.: the current value is complete its LSBs
+ // are stored in the upper bits
+ else if (right == 0 && left > 0) {
+
+ right = btr - left;
+ left = 0;
+ in_i++;
+
+ }
+ }
+ }
+ }
+ /* PQClean-edit: unused parameter */
+ (void)skip;
+}
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_uint16_t_unpack(uint16_t *out, const uint8_t *in,
+ size_t outlen, size_t inlen, uint8_t btr) {
+ size_t i;
+ uint8_t skip = 0;
+ uint8_t right, left;
+ size_t out_i;
+ if (btr <= 8) {
+ out_i = 0;
+ right = 8 - btr;
+ left = 0;
+ uint8_t mask = (1 << (btr)) - 1;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen; i++) {
+ skip = 0;
+ while (skip == 0 && out_i < outlen) {
+ out[out_i] |= (((in[i] >> (right)) << left) & mask);
+ //Case 1: right > 0, i.e. the current word is done
+ //and there is a new one waiting in the same input
+ if (right > 0) {
+ out_i++;
+ if (right >= btr) {
+ right -= btr;
+ } else {
+ left = btr - right;
+ right = 0;
+ }
+ }
+ //Case 2: right == 0 and left > BITS_TO_REPRESENT(Q-1),
+ //i.e. the current word continues in the next input
+ else if (right == 0) {
+ skip = 1;
+ right = 8 - left;
+ left = 0;
+ if (right == 0) {
+ right = 8 - btr;
+ }
+ }
+ }
+ }
+ } else if (btr == 8) {
+ for (i = 0; i < outlen; i++) {
+ out[i] = in[i];
+ }
+ } else if ((btr > 8) && (btr <= 16)) {
+ left = btr - 8;
+ right = 0;
+ out_i = 0;
+ skip = 0;
+ uint16_t mask = (1 << (btr)) - 1;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen; i++) {
+ skip = 0;
+ while (skip == 0 && out_i < outlen) {
+ // Shift some value of packed poly to correct position
+ // and OR it to the target value
+ out[out_i] |= ((((uint16_t)in[i] << left) >> right) & mask);
+ // First case: the value was incomplete,
+ // i.e. the LSBs are in the next block
+ // This means that left > 0 and right == 0.
+ if (left > 0 && right == 0) {
+ // Right shift of next element for remaining bits
+ if (left <= 8) {
+ right = 8 - left;
+ left = 0;
+ } else {
+ right = 0;
+ left -= 8;
+ }
+ skip = 1;
+ }
+ // Second case: the value was complete, i.e. the LSBs are now stored
+ else if (left == 0) {
+ if (right == 0) {
+ skip = 1;
+ left = btr - 8;
+ } else {
+ left = btr - right;
+ }
+ right = 0;
+ out_i++;
+ }
+ if (left == (btr)) {
+ left = 1;
+ }
+ }
+ }
+ }
+ /* PQClean-edit: unused parameter */
+ (void)skip;
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/pack_unpack.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/pack_unpack.h
new file mode 100644
index 000000000..0c1b4f24d
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/pack_unpack.h
@@ -0,0 +1,70 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ * @author Jonas Schupp
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include
+#include
+
+#include "parameters.h"
+
+/* compact Z_z/F_q vector encoding functions */
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_vec(uint8_t out[DENSELY_PACKED_FQ_VEC_SIZE],
+ const FQ_ELEM in[N]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fq_syn(uint8_t out[DENSELY_PACKED_FQ_SYN_SIZE],
+ const FQ_ELEM in[N - K]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_pack_fz_vec(uint8_t out[DENSELY_PACKED_FZ_VEC_SIZE],
+ const FZ_ELEM in[N]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_pack_fq(uint8_t *out, const FQ_ELEM *in,
+ size_t outlen, size_t inlen);
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_pack_fz(uint8_t *out, const FZ_ELEM *in,
+ size_t outlen, size_t inlen);
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fq_vec(FQ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FQ_VEC_SIZE]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fq_syn(FQ_ELEM out[N - K],
+ const uint8_t in[DENSELY_PACKED_FQ_SYN_SIZE]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_unpack_fz_vec(FZ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_unpack_fq(FQ_ELEM *out, const uint8_t *in,
+ size_t outlen, size_t inlen);
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_unpack_fz(FZ_ELEM *out, const uint8_t *in,
+ size_t outlen);
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_uint16_t_unpack(uint16_t *out, const uint8_t *in,
+ size_t outlen, size_t inlen, uint8_t btr);
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generic_uint16_t_pack(uint8_t *out, const uint16_t *in,
+ size_t outlen, size_t inlen, uint8_t btr);
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/parameters.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/parameters.h
new file mode 100644
index 000000000..6c9dc09f6
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/parameters.h
@@ -0,0 +1,131 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+#include
+
+#include "set.h"
+
+/******************************************************************************/
+/*************************** Base Fields Parameters ***************************/
+/******************************************************************************/
+
+/* The same base field and restriction are employed for all categories of RSDP */
+#define Q (127)
+#define Z ( 7)
+/* single-register table representation of E, the value of g^7=1 is also
+ * represented to avoid exponent renormalization*/
+#define RESTR_G_TABLE ((uint64_t) (0x0140201008040201))
+#define RESTR_G_GEN 2
+#define FQ_ELEM uint8_t
+#define FZ_ELEM uint8_t
+#define FQ_DOUBLEPREC uint16_t
+#define FQ_TRIPLEPREC uint32_t
+
+/******************************************************************************/
+/****************************** RSDP Parameters *******************************/
+/******************************************************************************/
+/********************************* Category 1 *********************************/
+#define SEC_MARGIN_LAMBDA (128)
+#define N (127)
+#define K ( 76)
+
+#define T (252)
+#define W (212)
+#define POSITION_IN_FW_STRING_T uint16_t
+
+/********************************* Category 3 *********************************/
+
+/******************************************************************************/
+/****************************** RSDP(G) Parameters ****************************/
+/******************************************************************************/
+
+#define HASH_CSPRNG_DOMAIN_SEP_CONST ((uint16_t)32768)
+
+/************* Helper macros for derived parameter computation ***************/
+
+#define ROUND_UP(amount, round_amt) ( (((amount)+(round_amt)-1)/(round_amt))*(round_amt) )
+
+#define IS_REPRESENTABLE_IN_D_BITS(D, N) \
+(((uint32_t) (N)>=(1UL << ((D)-1)) && (uint32_t) (N)<(1UL << (D))) ? (D) : -1)
+
+#define BITS_TO_REPRESENT(N) \
+ ((N) == 0 ? 1 : (15 \
+ + IS_REPRESENTABLE_IN_D_BITS( 1, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 2, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 3, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 4, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 5, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 6, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 7, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 8, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 9, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(10, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(11, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(12, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(13, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(14, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(15, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(16, N) \
+ ) \
+ )
+
+#define LOG2(L) ( (BITS_TO_REPRESENT(L) > BITS_TO_REPRESENT((L)-1)) ? (BITS_TO_REPRESENT((L)-1)) : (BITS_TO_REPRESENT(L)) )
+
+/***************** Derived parameters *****************************************/
+#define SEED_LENGTH_BYTES (SEC_MARGIN_LAMBDA/8)
+#define KEYPAIR_SEED_LENGTH_BYTES (2*(SEC_MARGIN_LAMBDA/8))
+#define HASH_DIGEST_LENGTH (2*(SEC_MARGIN_LAMBDA/8))
+#define SALT_LENGTH_BYTES (2*(SEC_MARGIN_LAMBDA/8))
+
+#define NUM_LEAVES_MERKLE_TREE (T)
+#define NUM_NODES_MERKLE_TREE (2*NUM_LEAVES_MERKLE_TREE-1)
+
+/*to be derived via script for each T/W*/
+#define NUM_LEAVES_SEED_TREE ( T )
+// #define NUM_NODES_SEED_TREE ( 2*NUM_LEAVES_SEED_TREE-1 )
+#define NUM_INNER_NODES_SEED_TREE ( NUM_NODES_SEED_TREE-NUM_LEAVES_SEED_TREE )
+
+/* Sizes of bitpacked field element vectors
+ * Bitpacking an n-elements vector of num_bits_for_q-1 bits long values
+ * will pack 8 values in num_bits_for_q-1 bytes exactly, leaving the remaining
+ * N % 8 as a tail */
+#define DENSELY_PACKED_FQ_VEC_SIZE ((N/8)*BITS_TO_REPRESENT(Q-1) + \
+ ROUND_UP( ((N%8)*BITS_TO_REPRESENT(Q-1)),8)/8)
+#define DENSELY_PACKED_FQ_SYN_SIZE (((N-K)/8)*BITS_TO_REPRESENT(Q-1) + \
+ ROUND_UP( (((N-K)%8)*BITS_TO_REPRESENT(Q-1)),8)/8)
+#define DENSELY_PACKED_FZ_VEC_SIZE ((N/8)*BITS_TO_REPRESENT(Z-1) + \
+ ROUND_UP( ((N%8)*BITS_TO_REPRESENT(Z-1)),8)/8)
+
+/* Derived parameters computed via compute_derived_parameters.py */
+#define TREE_NODES_TO_STORE 107
+#define NUM_NODES_SEED_TREE 504
+#define NODES_PER_LEVEL_ARRAY {1, 2, 4, 8, 16, 32, 63, 126, 252}
+#define MISSING_NODES_BEFORE_LEVEL_ARRAY {0, 0, 0, 0, 0, 0, 0, 1, 3}
+#define BITS_N_ZQ_CT_RNG 923
+#define BITS_BETA_ZQSTAR_CT_RNG 1817
+#define BITS_V_CT_RNG 27260
+#define BITS_N_ZZ_CT_RNG 493
+#define BITS_CWSTR_RNG 2102
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/restr_arith.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/restr_arith.h
new file mode 100644
index 000000000..a0824b738
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/restr_arith.h
@@ -0,0 +1,77 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "parameters.h"
+
+#define FZRED_SINGLE(x) (((x) & 0x07) + ((x) >> 3))
+#define FZRED_OPPOSITE(x) ((x) ^ 0x07)
+#define FZ_DOUBLE_ZERO_NORM(x) (((x) + (((x) + 1) >> 3)) & 0x07)
+
+static inline
+void fz_dz_norm_sigma(FZ_ELEM v[N]) {
+ for (int i = 0; i < N; i++) {
+ v[i] = FZ_DOUBLE_ZERO_NORM(v[i]);
+ }
+}
+
+/* Elements of the restricted subgroups are represented as the exponents of
+ * the generator */
+static inline
+void restr_vec_sub(FZ_ELEM res[N],
+ const FZ_ELEM a[N],
+ const FZ_ELEM b[N]) {
+ for (int i = 0; i < N; i++) {
+ res[i] = FZRED_SINGLE( a[i] + FZRED_OPPOSITE(b[i]) );
+ }
+}
+
+/* Given the choice of q and z, all elements of G are represented as n-elements
+ * vectors having powers-of-two in {1,2,...,64}.
+ * Employ a round of K&R-HW.
+ * Vectorized comb based HW is also employable, testing a word against
+ * 0x01...01
+ * note that 0x80 is not excluded as sigmas are in double-zero redundant repr.
+ */
+static inline
+int is_fq_vec_in_restr_group(const FQ_ELEM in[N]) {
+ int is_in_ok = 1;
+ for (int i = 0; i < N; i++) {
+ FQ_ELEM tmp;
+ tmp = ( in[i] - (FQ_ELEM)1 ) & in[i];
+ is_in_ok = is_in_ok && (tmp == 0);
+ }
+ return is_in_ok;
+}
+
+static inline
+int is_zz_vec_in_restr_group(const FZ_ELEM in[N]) {
+ int is_in_ok = 1;
+ for (int i = 0; i < N; i++) {
+ is_in_ok = is_in_ok && (in[i] < Z);
+ }
+ return is_in_ok;
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/seedtree.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/seedtree.c
new file mode 100644
index 000000000..10617a6a0
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/seedtree.c
@@ -0,0 +1,326 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include "seedtree.h"
+#include
+#include // memcpy(...), memset(...)
+
+#define LEFT_CHILD(i) (2*(i)+1)
+#define RIGHT_CHILD(i) (2*(i)+2)
+#define PARENT(i) (((i)-1)/2)
+
+/* Seed tree implementation. The binary seed tree is linearized into an array
+ * from root to leaves, and from left to right. The nodes are numbered picking
+ * the indexes from the corresponding full tree, having 2**LOG2(T) leaves */
+#define DIV_BY_TWO_CEIL(i) ((i)/2 + (i) % 2)
+
+#define TO_PUBLISH 1
+#define NOT_TO_PUBLISH 0
+
+/* maximum number of parallel executions of the CSPRNG */
+#define PAR_DEGREE 4
+
+/* PQClean-edit: avoid VLA */
+#define CSPRNG_INPUT_LEN (SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + SIZEOF_UINT16)
+//const uint32_t csprng_input_len = SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + sizeof(uint16_t);
+
+/*****************************************************************************/
+/**
+ * const unsigned char *indices: input parameter denoting an array
+ * with a number of binary cells equal to "leaves" representing
+ * the labels of the nodes identified as leaves of the tree[...]
+ * passed as second parameter.
+ * A label = 1 means that the byteseed of the node having the same index
+ * has to be released; = 0, otherwise.
+ *
+ * unsigned char *tree: input/output parameter denoting an array
+ * with a number of binary cells equal to "2*leaves-1";
+ * the first "leaves" cells (i.e., the ones with positions from 0 to leaves-1)
+ * are the ones that will be modified by the current subroutine,
+ * the last "leaves" cells will be a copy of the input array passed as first
+ * parameter.
+ *
+ * uint64_t leaves: input parameter;
+ *
+ */
+
+#define NUM_LEAVES_STENCIL_SEED_TREE ( 1UL << LOG2(T) )
+#define NUM_INNER_NODES_STENCIL_SEED_TREE ( NUM_LEAVES_STENCIL_SEED_TREE-1 )
+#define NUM_NODES_STENCIL_SEED_TREE ( 2*NUM_LEAVES_STENCIL_SEED_TREE-1 )
+
+static void compute_seeds_to_publish(
+ /* linearized binary tree of boolean nodes containing
+ * flags for each node 1-filled nodes are not to be
+ * released */
+ unsigned char flags_tree_to_publish[NUM_NODES_STENCIL_SEED_TREE],
+ /* Boolean Array indicating which of the T seeds must be
+ * released convention as per the above defines */
+ const unsigned char indices_to_publish[T]) {
+ /* the indices to publish may be less than the full leaves, copy them
+ * into the linearized tree leaves */
+ memcpy(flags_tree_to_publish + NUM_INNER_NODES_STENCIL_SEED_TREE,
+ indices_to_publish,
+ T);
+ memset(flags_tree_to_publish,
+ NOT_TO_PUBLISH,
+ NUM_INNER_NODES_STENCIL_SEED_TREE * sizeof(unsigned char));
+ /* compute the value for the internal nodes of the tree starting from the
+ * fathers of the leaves, right to left */
+ for (int i = NUM_LEAVES_STENCIL_SEED_TREE - 2; i >= 0; i--) {
+ if ( ( flags_tree_to_publish[LEFT_CHILD(i)] == TO_PUBLISH) &&
+ ( flags_tree_to_publish[RIGHT_CHILD(i)] == TO_PUBLISH) ) {
+ flags_tree_to_publish[i] = TO_PUBLISH;
+ }
+ }
+} /* end compute_seeds_to_publish */
+
+/**
+ * unsigned char *seed_tree:
+ * it is intended as an output parameter;
+ * storing the linearized binary seed tree
+ *
+ * The root seed is taken as a parameter.
+ * The seed of its TWO children are computed expanding (i.e., shake128...) the
+ * entropy in "salt" + "seedBytes of the parent" +
+ * "int, encoded over 16 bits - uint16_t, associated to each node
+ * from roots to leaves layer-by-layer from left to right,
+ * counting from 0 (the integer bound with the root node)"
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generate_seed_tree_from_root(unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ const unsigned char root_seed[SEED_LENGTH_BYTES],
+ const unsigned char salt[SALT_LENGTH_BYTES]) {
+ /* input buffer to the CSPRNG, contains a salt, the seed to be expanded
+ * and the integer index of the node being expanded for domain separation */
+ unsigned char csprng_inputs[PAR_DEGREE][CSPRNG_INPUT_LEN];
+
+ PAR_CSPRNG_STATE_T tree_csprng_state;
+
+ for (int i = 0; i < PAR_DEGREE; i++) {
+ memcpy(csprng_inputs[i] + SEED_LENGTH_BYTES, salt, SALT_LENGTH_BYTES);
+ }
+
+ uint16_t father_node_idxs[PAR_DEGREE];
+ uint16_t father_node_storage_idxs[PAR_DEGREE];
+
+ unsigned char *left_children[PAR_DEGREE];
+ unsigned char *right_children[PAR_DEGREE];
+
+ unsigned char discarded_seed[SEED_LENGTH_BYTES];
+
+ /* Set the root seed in the tree from the received parameter */
+ memcpy(seed_tree, root_seed, SEED_LENGTH_BYTES);
+
+ /* enqueue the calls to the CSPRNG */
+ int to_expand = 0;
+
+ /* reset left and right children */
+ /*
+ for(int i = 0; i < PAR_DEGREE; i++){
+ left_children[i] = discarded_seed;
+ right_children[i] = discarded_seed;
+ }
+ */
+
+ /* missing_nodes_before[i] contains the total number of missing nodes before
+ * level i (the root is level 0). This constant vector is precomputed */
+ const int missing_nodes_before[LOG2(T) + 1] = MISSING_NODES_BEFORE_LEVEL_ARRAY;
+ /* Generate the log_2(t) layers from the root, each iteration generates a tree
+ * level; iterate on nodes of the parent level */
+ const int nodes_in_level[LOG2(T) + 1] = NODES_PER_LEVEL_ARRAY;
+ int ancestors = 0;
+ for (int level = 0; level < LOG2(T); level++) {
+ for (int node_in_level = 0; node_in_level < nodes_in_level[level]; node_in_level++ ) {
+
+ to_expand++;
+
+ father_node_idxs[to_expand - 1] = ancestors + node_in_level;
+ father_node_storage_idxs[to_expand - 1] = father_node_idxs[to_expand - 1] - missing_nodes_before[level];
+
+ /* prepare the children of node i to be expanded */
+ memcpy(csprng_inputs[to_expand - 1], seed_tree + father_node_storage_idxs[to_expand - 1]*SEED_LENGTH_BYTES, SEED_LENGTH_BYTES);
+ *((uint16_t *)(csprng_inputs[to_expand - 1] + SALT_LENGTH_BYTES + SEED_LENGTH_BYTES)) = father_node_idxs[to_expand - 1];
+ left_children[to_expand - 1] = seed_tree + (LEFT_CHILD(father_node_idxs[to_expand - 1]) - missing_nodes_before[level + 1]) * SEED_LENGTH_BYTES;
+ /* the last leaf might not be needed */
+ if ((RIGHT_CHILD(father_node_idxs[to_expand - 1]) - missing_nodes_before[level + 1]) < NUM_NODES_SEED_TREE ) {
+ right_children[to_expand - 1] = seed_tree + (RIGHT_CHILD(father_node_idxs[to_expand - 1]) - missing_nodes_before[level + 1]) * SEED_LENGTH_BYTES;
+ } else {
+ right_children[to_expand - 1] = discarded_seed;
+ }
+
+ /* call CSPRNG in batches of 4 (or less when changing tree level) */
+ if (to_expand == PAR_DEGREE || (node_in_level == nodes_in_level[level] - 1)) {
+ par_initialize_csprng(to_expand, &tree_csprng_state, csprng_inputs[0], csprng_inputs[1], csprng_inputs[2], csprng_inputs[3], CSPRNG_INPUT_LEN);
+ par_csprng_randombytes(to_expand, &tree_csprng_state, left_children[0], left_children[1], left_children[2], left_children[3], SEED_LENGTH_BYTES);
+ par_csprng_randombytes(to_expand, &tree_csprng_state, right_children[0], right_children[1], right_children[2], right_children[3], SEED_LENGTH_BYTES);
+ par_csprng_release(to_expand, &tree_csprng_state);
+ to_expand = 0;
+ }
+
+ }
+ ancestors += (1L << level);
+ }
+} /* end generate_seed_tree */
+
+/*****************************************************************************/
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_publish_seeds(unsigned char *seed_storage,
+ // OUTPUT: sequence of seeds to be released
+ const unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ // INPUT: binary array storing in each cell a binary value (i.e., 0 or 1),
+ // which in turn denotes if the seed of the node with the same index
+ // must be released (i.e., cell == 0) or not (i.e., cell == 1).
+ // Indeed the seed will be stored in the sequence computed as a result into the out[...] array.
+ // INPUT: binary array denoting which node has to be released (cell == TO_PUBLISH) or not
+ const unsigned char indices_to_publish[T]
+ ) {
+ /* complete linearized binary tree containing boolean values determining
+ * if a node is to be released or not. Nodes set to 1 are not to be released
+ * oldest ancestor of sets of nodes equal to 0 are to be released */
+ unsigned char flags_tree_to_publish[NUM_NODES_STENCIL_SEED_TREE] = {0};
+ compute_seeds_to_publish(flags_tree_to_publish, indices_to_publish);
+ const int missing_nodes_before[LOG2(T) + 1] = MISSING_NODES_BEFORE_LEVEL_ARRAY;
+ const int nodes_in_level[LOG2(T) + 1] = NODES_PER_LEVEL_ARRAY;
+
+ int num_seeds_published = 0;
+ int node_idx = 1;
+ /* no sense in trying to publish the root node, start examining from level 1
+ * */
+
+ int ancestors = 1;
+ for (int level = 1; level < LOG2(T) + 1; level++) {
+ for (int node_in_level = 0; node_in_level < nodes_in_level[level]; node_in_level++ ) {
+ node_idx = ancestors + node_in_level;
+ int node_storage_idx = node_idx - missing_nodes_before[level];
+ if ( (flags_tree_to_publish[node_idx] == TO_PUBLISH) &&
+ (flags_tree_to_publish[PARENT(node_idx)] == NOT_TO_PUBLISH) ) {
+ memcpy(seed_storage + num_seeds_published * SEED_LENGTH_BYTES,
+ seed_tree + node_storage_idx * SEED_LENGTH_BYTES,
+ SEED_LENGTH_BYTES);
+ num_seeds_published++;
+ }
+ }
+ ancestors += (1L << level);
+ }
+
+ return num_seeds_published;
+} /* end PQCLEAN_CROSSRSDP128BALANCED_AVX2_publish_seeds */
+
+/*****************************************************************************/
+
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_regenerate_round_seeds(unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ const unsigned char indices_to_publish[T],
+ const unsigned char *stored_seeds,
+ const unsigned char salt[SALT_LENGTH_BYTES]) {
+ /* complete linearized binary tree containing boolean values determining
+ * if a node is to be released or not. Nodes set to 1 are not to be released
+ * oldest ancestor of sets of nodes equal to 0 are to be released */
+ unsigned char flags_tree_to_publish[NUM_NODES_STENCIL_SEED_TREE] = {0};
+ compute_seeds_to_publish(flags_tree_to_publish, indices_to_publish);
+
+ unsigned char csprng_inputs[PAR_DEGREE][CSPRNG_INPUT_LEN];
+
+ PAR_CSPRNG_STATE_T tree_csprng_state;
+
+ for (int i = 0; i < PAR_DEGREE; i++) {
+ memcpy(csprng_inputs[i] + SEED_LENGTH_BYTES, salt, SALT_LENGTH_BYTES);
+ }
+
+ uint16_t father_node_idxs[PAR_DEGREE];
+ uint16_t father_node_storage_idxs[PAR_DEGREE];
+
+ unsigned char *left_children[PAR_DEGREE];
+ unsigned char *right_children[PAR_DEGREE];
+
+ unsigned char discarded_seed[SEED_LENGTH_BYTES];
+
+ int nodes_used = 0;
+
+ /* missing_nodes_before[i] contains the total number of missing nodes before
+ * level i. Level 0 is taken to be the tree root This constant vector is precomputed */
+ const int missing_nodes_before[LOG2(T) + 1] = MISSING_NODES_BEFORE_LEVEL_ARRAY;
+
+ int ancestors = 0;
+ const int nodes_in_level[LOG2(T) + 1] = NODES_PER_LEVEL_ARRAY;
+
+ /* enqueue the calls to the CSPRNG */
+ int to_expand = 0;
+
+ /* regenerating the seed tree never starts from the root, as it is never
+ * disclosed */
+ ancestors = 0;
+
+ for (int level = 0; level <= LOG2(T); level++) {
+
+ for (int node_in_level = 0; node_in_level < nodes_in_level[level]; node_in_level++ ) {
+
+ /* skip unpublished nodes */
+ if (flags_tree_to_publish[ancestors + node_in_level] == TO_PUBLISH) {
+
+ uint16_t father_node_idx = ancestors + node_in_level;
+ uint16_t father_node_storage_idx = father_node_idx - missing_nodes_before[level];
+
+ /* if the node is published and an orphan then memcpy it from the proof */
+ if ( flags_tree_to_publish[PARENT(father_node_idx)] == NOT_TO_PUBLISH ) {
+ memcpy(seed_tree + SEED_LENGTH_BYTES * (father_node_storage_idx),
+ stored_seeds + SEED_LENGTH_BYTES * nodes_used,
+ SEED_LENGTH_BYTES );
+ nodes_used++;
+ }
+
+ /* if the node is published and not a leaf then its children need to be expanded */
+ if (level < LOG2(T)) {
+ to_expand++;
+ /* prepare the childen to be expanded */
+ father_node_idxs[to_expand - 1] = father_node_idx;
+ father_node_storage_idxs[to_expand - 1] = father_node_storage_idx;
+ memcpy(csprng_inputs[to_expand - 1], seed_tree + father_node_storage_idxs[to_expand - 1]*SEED_LENGTH_BYTES, SEED_LENGTH_BYTES);
+ *((uint16_t *)(csprng_inputs[to_expand - 1] + SALT_LENGTH_BYTES + SEED_LENGTH_BYTES)) = father_node_idxs[to_expand - 1];
+ left_children[to_expand - 1] = seed_tree + (LEFT_CHILD(father_node_idxs[to_expand - 1]) - missing_nodes_before[level + 1]) * SEED_LENGTH_BYTES;
+ /* the last leaf might not be needed */
+ if ((RIGHT_CHILD(father_node_idxs[to_expand - 1]) - missing_nodes_before[level + 1]) < NUM_NODES_SEED_TREE ) {
+ right_children[to_expand - 1] = seed_tree + (RIGHT_CHILD(father_node_idxs[to_expand - 1]) - missing_nodes_before[level + 1]) * SEED_LENGTH_BYTES;
+ } else {
+ right_children[to_expand - 1] = discarded_seed;
+ }
+ }
+ }
+
+ /* call CSPRNG in batches of 4 (or less when changing tree level) */
+ if (level < LOG2(T)) {
+ if (to_expand == PAR_DEGREE || (node_in_level == nodes_in_level[level] - 1)) {
+ par_initialize_csprng(to_expand, &tree_csprng_state, csprng_inputs[0], csprng_inputs[1], csprng_inputs[2], csprng_inputs[3], CSPRNG_INPUT_LEN);
+ par_csprng_randombytes(to_expand, &tree_csprng_state, left_children[0], left_children[1], left_children[2], left_children[3], SEED_LENGTH_BYTES);
+ par_csprng_randombytes(to_expand, &tree_csprng_state, right_children[0], right_children[1], right_children[2], right_children[3], SEED_LENGTH_BYTES);
+ par_csprng_release(to_expand, &tree_csprng_state);
+ to_expand = 0;
+ }
+ }
+ }
+ ancestors += (1L << level);
+ }
+ return nodes_used;
+} /* end regenerate_leaves */
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/seedtree.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/seedtree.h
new file mode 100644
index 000000000..79f6c3bab
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/seedtree.h
@@ -0,0 +1,54 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "csprng_hash.h"
+#include "parameters.h"
+
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_pseed(unsigned char seed[SEED_LENGTH_BYTES]);
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_ptree(unsigned char seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES]);
+
+/******************************************************************************/
+void PQCLEAN_CROSSRSDP128BALANCED_AVX2_generate_seed_tree_from_root(unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ const unsigned char root_seed[SEED_LENGTH_BYTES],
+ const unsigned char salt[SALT_LENGTH_BYTES]) ;
+
+/******************************************************************************/
+/* returns the number of seeds which have been published */
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_publish_seeds(unsigned char *seed_storage,
+ const unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ // binary array denoting if node has to be released (cell == 0) or not
+ const unsigned char indices_to_publish[T]);
+
+/******************************************************************************/
+/* returns the number of seeds which have been used to regenerate the tree */
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_regenerate_round_seeds(unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ const unsigned char indices_to_publish[T],
+ const unsigned char *stored_seeds,
+ const unsigned char salt[SALT_LENGTH_BYTES]); // input
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/set.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/set.h
new file mode 100644
index 000000000..9257a8df8
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/set.h
@@ -0,0 +1,25 @@
+
+#define RSDP 1
+#define CATEGORY_1 1
+#define BALANCED 1
+
+#undef NO_TREES
+
+/* liboqs-edit: when compiling avx2 just assume that Intel Instrinsics are available */
+#define IMPLEMENTATION_avx2
+#define HIGH_COMPATIBILITY_X86_64
+#define HIGH_PERFORMANCE_X86_64
+
+/* PQClean-edit: avoid VLA (don't call sizeof() when creating arrays) */
+#define SIZEOF_UINT16 2
+
+/* Undefine unused macros to facilitate dead code removal using unifdef */
+#undef SHA_3_LIBKECCAK
+/* Variant */
+#undef RSDPG
+/* Category */
+#undef CATEGORY_3
+#undef CATEGORY_5
+/* Target */
+#undef SPEED
+#undef SIG_SIZE
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/sha3.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/sha3.h
new file mode 100644
index 000000000..5045aaeeb
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/sha3.h
@@ -0,0 +1,146 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "fips202.h"
+/* standalone FIPS-202 implementation has
+ * different states for SHAKE depending on security level*/
+#define SHAKE_STATE_STRUCT shake128incctx
+// %%%%%%%%%%%%%%%%%% Self-contained SHAKE x1 Wrappers %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+static inline
+void xof_shake_init(SHAKE_STATE_STRUCT *state, int val) {
+ /* PQClean-edit: unused parameter */
+ (void)val;
+ shake128_inc_init(state);
+}
+
+static inline
+void xof_shake_update(SHAKE_STATE_STRUCT *state,
+ const unsigned char *input,
+ uint32_t inputByteLen) {
+ shake128_inc_absorb(state,
+ (const uint8_t *)input,
+ inputByteLen);
+}
+
+static inline
+void xof_shake_final(SHAKE_STATE_STRUCT *state) {
+ shake128_inc_finalize(state);
+}
+
+static inline
+void xof_shake_extract(SHAKE_STATE_STRUCT *state,
+ unsigned char *output,
+ uint32_t outputByteLen) {
+ shake128_inc_squeeze(output, outputByteLen, state);
+}
+
+/* PQClean-edit: CSPRNG release context */
+static inline
+void xof_shake_release(SHAKE_STATE_STRUCT *state) {
+ shake128_inc_ctx_release(state);
+}
+
+// %%%%%%%%%%%%%%%%%% Self-contained SHAKE x4 Wrappers %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#include "fips202x4.h"
+#define SHAKE_X4_STATE_STRUCT shake128x4incctx
+#define SHAKE_X4_INIT shake128x4_inc_init
+#define SHAKE_X4_ABSORB shake128x4_inc_absorb
+#define SHAKE_X4_FINALIZE shake128x4_inc_finalize
+#define SHAKE_X4_SQUEEZE shake128x4_inc_squeeze
+#define SHAKE_X4_RELEASE shake128x4_inc_ctx_release
+
+static inline void xof_shake_x4_init(SHAKE_X4_STATE_STRUCT *states) {
+ SHAKE_X4_INIT(states);
+}
+static inline void xof_shake_x4_update(SHAKE_X4_STATE_STRUCT *states,
+ const unsigned char *in1,
+ const unsigned char *in2,
+ const unsigned char *in3,
+ const unsigned char *in4,
+ uint32_t singleInputByteLen) {
+ SHAKE_X4_ABSORB(states, in1, in2, in3, in4, singleInputByteLen);
+}
+static inline void xof_shake_x4_final(SHAKE_X4_STATE_STRUCT *states) {
+ SHAKE_X4_FINALIZE(states);
+}
+static inline void xof_shake_x4_extract(SHAKE_X4_STATE_STRUCT *states,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3,
+ unsigned char *out4,
+ uint32_t singleOutputByteLen) {
+ SHAKE_X4_SQUEEZE(out1, out2, out3, out4, singleOutputByteLen, states);
+}
+static inline void xof_shake_x4_release(SHAKE_X4_STATE_STRUCT *states) {
+ SHAKE_X4_RELEASE(states);
+}
+
+// %%%%%%%%%%%%%%%%%% Self-contained SHAKE x2 Wrappers %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+/* SHAKE_x2 just calls SHAKE_x1 twice. If a suitable SHAKE_x2 implementation becomes available, it should be used instead */
+
+typedef struct {
+ SHAKE_STATE_STRUCT state1;
+ SHAKE_STATE_STRUCT state2;
+} shake_x2_ctx;
+#define SHAKE_X2_STATE_STRUCT shake_x2_ctx
+static inline void xof_shake_x2_init(SHAKE_X2_STATE_STRUCT *states) {
+ xof_shake_init(&(states->state1), 0);
+ xof_shake_init(&(states->state2), 0);
+}
+static inline void xof_shake_x2_update(SHAKE_X2_STATE_STRUCT *states,
+ const unsigned char *in1,
+ const unsigned char *in2,
+ uint32_t singleInputByteLen) {
+ xof_shake_update(&(states->state1), (const uint8_t *)in1, singleInputByteLen);
+ xof_shake_update(&(states->state2), (const uint8_t *)in2, singleInputByteLen);
+}
+static inline void xof_shake_x2_final(SHAKE_X2_STATE_STRUCT *states) {
+ xof_shake_final(&(states->state1));
+ xof_shake_final(&(states->state2));
+}
+static inline void xof_shake_x2_extract(SHAKE_X2_STATE_STRUCT *states,
+ unsigned char *out1,
+ unsigned char *out2,
+ uint32_t singleOutputByteLen) {
+ xof_shake_extract(&(states->state1), out1, singleOutputByteLen);
+ xof_shake_extract(&(states->state2), out2, singleOutputByteLen);
+}
+static inline void xof_shake_x2_release(SHAKE_X2_STATE_STRUCT *states) {
+ xof_shake_release(&(states->state1));
+ xof_shake_release(&(states->state2));
+}
+
+// %%%%%%%%%%%%%%%%%%%% Parallel SHAKE State Struct %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+typedef struct {
+ SHAKE_STATE_STRUCT state1;
+ SHAKE_X2_STATE_STRUCT state2;
+ SHAKE_X4_STATE_STRUCT state4;
+} par_shake_ctx;
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/sign.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/sign.c
new file mode 100644
index 000000000..810001ab1
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_avx2/sign.c
@@ -0,0 +1,122 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include "api.h"
+#include "CROSS.h"
+#include "parameters.h"
+#include // size_t
+#include // memcpy
+/*----------------------------------------------------------------------------*/
+
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_keypair(unsigned char *pk,
+ unsigned char *sk) {
+ /* keygen cannot fail */
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_CROSS_keygen((prikey_t *) sk,
+ (pubkey_t *) pk);
+
+ return 0; // NIST convention: 0 == zero errors
+} // end PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_keypair
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*... generating a signed message sm[0],sm[1],...,sm[*smlen-1] */
+/*... from original message m[0],m[1],...,m[mlen-1] */
+/*... under secret key sk[0],sk[1],... */
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign(unsigned char *sm,
+ size_t *smlen, // out parameter
+ const unsigned char *m, size_t mlen, // in parameter
+ const unsigned char *sk) { // in parameter
+ /* sign cannot fail */
+ memcpy(sm, m, mlen);
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_CROSS_sign((const prikey_t *) sk, // in parameter
+ (const char *const) m, (const size_t) mlen, // in parameter
+ (CROSS_sig_t *) (sm + mlen)); // out parameter
+ *smlen = mlen + (size_t) sizeof(CROSS_sig_t);
+
+ return 0; // NIST convention: 0 == zero errors
+} // end PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*. ... verifying a signed message sm[0],sm[1],...,sm[smlen-1] */
+/*. ... under public key pk[0],pk[1],... */
+/*. ... and producing original message m[0],m[1],...,m[*mlen-1] */
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_open(unsigned char *m,
+ size_t *mlen, // out parameter
+ const unsigned char *sm, size_t smlen, // in parameter
+ const unsigned char *pk) { // in parameter
+
+ /* verify returns 1 if signature is ok, 0 otherwise */
+ *mlen = smlen - (size_t) sizeof(CROSS_sig_t);
+
+ memcpy((unsigned char *) m, (const unsigned char *) sm, (size_t) *mlen);
+ int ok = PQCLEAN_CROSSRSDP128BALANCED_AVX2_CROSS_verify((const pubkey_t *const)
+ pk, // in parameter
+ (const char *const) m, (const size_t) * mlen, // in parameter
+ (const CROSS_sig_t *const) (sm + *mlen)); // in parameter
+
+ return ok - 1; // NIST convention: 0 == zero errors, -1 == error condition
+} // end PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_open
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*... generating a signature sig[0],sig[1],...,sig[*siglen-1] */
+/*... from original message m[0],m[1],...,m[mlen-1] */
+/*... under secret key sk[0],sk[1],... */
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_signature(unsigned char *sig, size_t *siglen, // out parameter
+ const unsigned char *m, size_t mlen, // in parameter
+ const unsigned char *sk // in parameter
+ ) {
+ /* sign cannot fail */
+ PQCLEAN_CROSSRSDP128BALANCED_AVX2_CROSS_sign((const prikey_t *) sk, // in parameter
+ (const char *const) m, (const size_t) mlen, // in parameter
+ (CROSS_sig_t *) sig); // out parameter
+ *siglen = (size_t) sizeof(CROSS_sig_t);
+
+ return 0; // NIST convention: 0 == zero errors
+} // end PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_signature
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*. ... verifying a signature sig[0],sig[1],...,sig[siglen-1] */
+/*. ... under public key pk[0],pk[1],... */
+/*. ... and producing original message m[0],m[1],...,m[*mlen-1] */
+int PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_verify(const unsigned char *sig, size_t siglen, // in parameter
+ const unsigned char *m, size_t mlen, // in parameter
+ const unsigned char *pk // in parameter
+ ) {
+
+ /* PQClean-edit: unused parameter */
+ (void)siglen;
+
+ /* verify returns 1 if signature is ok, 0 otherwise */
+ int ok = PQCLEAN_CROSSRSDP128BALANCED_AVX2_CROSS_verify((const pubkey_t *const) pk, // in parameter
+ (const char *const) m, (const size_t) mlen, // in parameter
+ (const CROSS_sig_t *const) sig); // in parameter
+
+ return ok - 1; // NIST convention: 0 == zero errors, -1 == error condition
+} // end PQCLEAN_CROSSRSDP128BALANCED_AVX2_crypto_sign_verify
+
+/*----------------------------------------------------------------------------*/
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/CROSS.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/CROSS.c
new file mode 100644
index 000000000..0f84a39b5
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/CROSS.c
@@ -0,0 +1,454 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+#include
+#include
+
+#include "CROSS.h"
+#include "csprng_hash.h"
+#include "fq_arith.h"
+#include "merkle_tree.h"
+#include "pack_unpack.h"
+#include "randombytes.h"
+#include "seedtree.h"
+
+static
+void expand_public_seed(FQ_ELEM V_tr[K][N - K],
+ const uint8_t seed_pub[KEYPAIR_SEED_LENGTH_BYTES]) {
+ CSPRNG_STATE_T CSPRNG_state_mat;
+ initialize_csprng(&CSPRNG_state_mat, seed_pub, KEYPAIR_SEED_LENGTH_BYTES);
+ CSPRNG_fq_mat(V_tr, &CSPRNG_state_mat);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_mat);
+}
+
+static
+void expand_private_seed(FZ_ELEM eta[N],
+ FQ_ELEM V_tr[K][N - K],
+ const uint8_t seed[KEYPAIR_SEED_LENGTH_BYTES]) {
+ uint8_t seede_seed_pub[2][KEYPAIR_SEED_LENGTH_BYTES];
+ CSPRNG_STATE_T CSPRNG_state;
+ initialize_csprng(&CSPRNG_state, seed, KEYPAIR_SEED_LENGTH_BYTES);
+ csprng_randombytes((uint8_t *)seede_seed_pub,
+ 2 * KEYPAIR_SEED_LENGTH_BYTES,
+ &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ expand_public_seed(V_tr, seede_seed_pub[1]);
+
+ CSPRNG_STATE_T CSPRNG_state_eta;
+ initialize_csprng(&CSPRNG_state_eta, seede_seed_pub[0], KEYPAIR_SEED_LENGTH_BYTES);
+ CSPRNG_zz_vec(eta, &CSPRNG_state_eta);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_eta);
+}
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CROSS_keygen(prikey_t *SK,
+ pubkey_t *PK) {
+ /* generation of random material for public and private key */
+ randombytes(SK->seed, KEYPAIR_SEED_LENGTH_BYTES);
+ uint8_t seede_seed_pub[2][KEYPAIR_SEED_LENGTH_BYTES];
+
+ CSPRNG_STATE_T CSPRNG_state;
+ initialize_csprng(&CSPRNG_state, SK->seed, KEYPAIR_SEED_LENGTH_BYTES);
+ csprng_randombytes((uint8_t *)seede_seed_pub,
+ 2 * KEYPAIR_SEED_LENGTH_BYTES,
+ &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ memcpy(PK->seed_pub, seede_seed_pub[1], KEYPAIR_SEED_LENGTH_BYTES);
+
+ /* expansion of matrix/matrices */
+ FQ_ELEM V_tr[K][N - K];
+ expand_public_seed(V_tr, PK->seed_pub);
+
+ /* expansion of secret key material */
+ FZ_ELEM eta[N];
+ CSPRNG_STATE_T CSPRNG_state_eta;
+ initialize_csprng(&CSPRNG_state_eta, seede_seed_pub[0], KEYPAIR_SEED_LENGTH_BYTES);
+
+ CSPRNG_zz_vec(eta, &CSPRNG_state_eta);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_eta);
+
+ /* compute public syndrome */
+ FQ_ELEM pub_syn[N - K];
+ restr_vec_by_fq_matrix(pub_syn, eta, V_tr);
+ fq_dz_norm_synd(pub_syn);
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_syn(PK->s, pub_syn);
+}
+
+/* sign cannot fail */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CROSS_sign(const prikey_t *const SK,
+ const char *const m,
+ const size_t mlen,
+ CROSS_sig_t *const sig) {
+ /* Wipe any residual information in the sig structure allocated by the
+ * caller */
+ memset(sig, 0, sizeof(CROSS_sig_t));
+ /* Key material expansion */
+ FQ_ELEM V_tr[K][N - K];
+ FZ_ELEM eta[N];
+ expand_private_seed(eta, V_tr, SK->seed);
+
+ uint8_t root_seed[SEED_LENGTH_BYTES];
+ randombytes(root_seed, SEED_LENGTH_BYTES);
+ randombytes(sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t seed_tree[SEED_LENGTH_BYTES * NUM_NODES_SEED_TREE] = {0};
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generate_seed_tree_from_root(seed_tree, root_seed, sig->salt);
+ uint8_t *rounds_seeds = seed_tree +
+ SEED_LENGTH_BYTES * NUM_INNER_NODES_SEED_TREE;
+
+ FZ_ELEM eta_tilde[T][N];
+ FZ_ELEM sigma[T][N];
+ FQ_ELEM u_tilde[T][N];
+ FQ_ELEM s_tilde[N - K];
+
+ uint8_t cmt_0_i_input[DENSELY_PACKED_FQ_SYN_SIZE +
+ DENSELY_PACKED_FZ_VEC_SIZE +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ const int offset_salt = DENSELY_PACKED_FQ_SYN_SIZE + DENSELY_PACKED_FZ_VEC_SIZE;
+ const int offset_round_idx = offset_salt + SALT_LENGTH_BYTES;
+ /* cmt_0_i_input is syndrome||sigma ||salt ; place salt at the end */
+ memcpy(cmt_0_i_input + offset_salt, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t cmt_1_i_input[SEED_LENGTH_BYTES +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ /* cmt_1_i_input is concat(seed,salt,round index) */
+ memcpy(cmt_1_i_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t cmt_0[T][HASH_DIGEST_LENGTH] = {0};
+ uint8_t cmt_1[T][HASH_DIGEST_LENGTH] = {0};
+
+ CSPRNG_STATE_T CSPRNG_state;
+ for (uint16_t i = 0; i < T; i++) {
+ /* CSPRNG is fed with concat(seed,salt,round index) represented
+ * as a 2 bytes little endian unsigned integer */
+ uint8_t csprng_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ memcpy(csprng_input, rounds_seeds + SEED_LENGTH_BYTES * i, SEED_LENGTH_BYTES);
+ memcpy(csprng_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ /* i+c */
+ uint16_t domain_sep_i = i + NUM_NODES_SEED_TREE;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES] = (domain_sep_i >> 8) & 0xFF;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + 1] = domain_sep_i & 0xFF;
+
+ /* expand seed[i] into seed_e and seed_u */
+ initialize_csprng(&CSPRNG_state,
+ csprng_input,
+ SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t));
+ /* expand eta_tilde */
+ CSPRNG_zz_vec(eta_tilde[i], &CSPRNG_state);
+ restr_vec_sub(sigma[i], eta, eta_tilde[i]);
+
+ FQ_ELEM v[N];
+ convert_restr_vec_to_fq(v, sigma[i]);
+ fz_dz_norm_sigma(sigma[i]);
+ /* expand u_tilde */
+ CSPRNG_fq_vec(u_tilde[i], &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ FQ_ELEM u[N];
+ fq_vec_by_fq_vec_pointwise(u, v, u_tilde[i]);
+ fq_vec_by_fq_matrix(s_tilde, u, V_tr);
+ fq_dz_norm_synd(s_tilde);
+
+ /* cmt_0_i_input contains s-tilde || sigma_i || salt */
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_syn(cmt_0_i_input, s_tilde);
+
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fz_vec(cmt_0_i_input + DENSELY_PACKED_FQ_SYN_SIZE, sigma[i]);
+ /* Fixed endianness marshalling of round counter
+ * i+c+dsc */
+ uint16_t domain_sep_idx_hash = domain_sep_i + HASH_CSPRNG_DOMAIN_SEP_CONST;
+ cmt_0_i_input[offset_round_idx] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_0_i_input[offset_round_idx + 1] = domain_sep_idx_hash & 0xFF;
+
+ hash(cmt_0[i], cmt_0_i_input, sizeof(cmt_0_i_input));
+ memcpy(cmt_1_i_input,
+ rounds_seeds + SEED_LENGTH_BYTES * i,
+ SEED_LENGTH_BYTES);
+
+ cmt_1_i_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_1_i_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + 1] = domain_sep_idx_hash & 0xFF;
+ hash(cmt_1[i], cmt_1_i_input, sizeof(cmt_1_i_input));
+
+ }
+
+ /* vector containing d_0 and d_1 from spec */
+ uint8_t commit_digests[2][HASH_DIGEST_LENGTH];
+ uint8_t merkle_tree_0[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH];
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_merkle_tree_root_compute(commit_digests[0], merkle_tree_0, cmt_0);
+ hash(commit_digests[1], (unsigned char *)cmt_1, sizeof(cmt_1));
+ hash(sig->digest_01,
+ (unsigned char *) commit_digests,
+ sizeof(commit_digests));
+
+ /* first challenge extraction */
+ uint8_t beta_buf[2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES];
+ /* place d_m at the beginning of the input of the hash generating d_beta*/
+ hash(beta_buf, (uint8_t *) m, mlen);
+ memcpy(beta_buf + HASH_DIGEST_LENGTH, sig->digest_01, HASH_DIGEST_LENGTH);
+ memcpy(beta_buf + 2 * HASH_DIGEST_LENGTH, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t d_beta[HASH_DIGEST_LENGTH];
+ hash(d_beta, beta_buf, 2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES);
+
+ FQ_ELEM beta[T];
+ initialize_csprng(&CSPRNG_state, d_beta, HASH_DIGEST_LENGTH);
+ CSPRNG_fq_vec_beta(beta, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ /* Computation of the first round of responses */
+ FQ_ELEM y[T][N];
+ for (int i = 0; i < T; i++) {
+ fq_vec_by_restr_vec_scaled(y[i],
+ eta_tilde[i],
+ beta[i],
+ u_tilde[i]);
+ fq_dz_norm(y[i]);
+ }
+ /* y vectors are packed before being hashed */
+ uint8_t digest_b_buf[T * DENSELY_PACKED_FQ_VEC_SIZE + HASH_DIGEST_LENGTH];
+ for (int x = 0; x < T; x++) {
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_vec(digest_b_buf + (x * DENSELY_PACKED_FQ_VEC_SIZE), y[x]);
+ }
+ /* Second challenge extraction */
+ memcpy(digest_b_buf + T * DENSELY_PACKED_FQ_VEC_SIZE, d_beta, HASH_DIGEST_LENGTH);
+
+ hash(sig->digest_b, digest_b_buf, sizeof(digest_b_buf));
+
+ uint8_t fixed_weight_b[T] = {0};
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_expand_digest_to_fixed_weight(fixed_weight_b, sig->digest_b);
+
+ /* Computation of the second round of responses */
+
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_merkle_tree_proof_compute(sig->mtp, merkle_tree_0, fixed_weight_b);
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_publish_seeds(sig->stp, seed_tree, fixed_weight_b);
+
+ int published_rsps = 0;
+ for (int i = 0; i < T; i++) {
+ if (fixed_weight_b[i] == 0) {
+ /* PQClean-edit: remove assertion */
+ //assert(published_rsps < T-W);
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_vec(sig->rsp_0[published_rsps].y, y[i]);
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fz_vec(sig->rsp_0[published_rsps].sigma, sigma[i]);
+ memcpy(sig->rsp_1[published_rsps], cmt_1[i], HASH_DIGEST_LENGTH);
+ published_rsps++;
+ }
+ }
+}
+
+/* PQClean-edit: avoid VLA */
+#define CSPRNG_INPUT_LENGTH (SALT_LENGTH_BYTES+SEED_LENGTH_BYTES+SIZEOF_UINT16)
+//const int csprng_input_length = SALT_LENGTH_BYTES+SEED_LENGTH_BYTES+sizeof(uint16_t);
+
+/* verify returns 1 if signature is ok, 0 otherwise */
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CROSS_verify(const pubkey_t *const PK,
+ const char *const m,
+ const size_t mlen,
+ const CROSS_sig_t *const sig) {
+ CSPRNG_STATE_T CSPRNG_state;
+
+ FQ_ELEM V_tr[K][N - K];
+ expand_public_seed(V_tr, PK->seed_pub);
+
+ FQ_ELEM pub_syn[N - K];
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fq_syn(pub_syn, PK->s);
+
+ uint8_t beta_buf[2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES];
+ hash(beta_buf, (uint8_t *) m, mlen);
+ memcpy(beta_buf + HASH_DIGEST_LENGTH, sig->digest_01, HASH_DIGEST_LENGTH);
+ memcpy(beta_buf + 2 * HASH_DIGEST_LENGTH, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t d_beta[HASH_DIGEST_LENGTH];
+ hash(d_beta, beta_buf, sizeof(beta_buf));
+
+ FQ_ELEM beta[T];
+ initialize_csprng(&CSPRNG_state, d_beta, HASH_DIGEST_LENGTH);
+ CSPRNG_fq_vec_beta(beta, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ uint8_t fixed_weight_b[T] = {0};
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_expand_digest_to_fixed_weight(fixed_weight_b, sig->digest_b);
+
+ uint8_t seed_tree[SEED_LENGTH_BYTES * NUM_NODES_SEED_TREE] = {0};
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_regenerate_round_seeds(seed_tree, fixed_weight_b, sig->stp, sig->salt);
+ uint8_t *rounds_seeds = seed_tree +
+ SEED_LENGTH_BYTES * NUM_INNER_NODES_SEED_TREE;
+
+ uint8_t cmt_0_i_input[DENSELY_PACKED_FQ_SYN_SIZE +
+ DENSELY_PACKED_FZ_VEC_SIZE +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ const int offset_salt = DENSELY_PACKED_FQ_SYN_SIZE + DENSELY_PACKED_FZ_VEC_SIZE;
+ const int offset_round_idx = offset_salt + SALT_LENGTH_BYTES;
+ /* cmt_0_i_input is syndrome||sigma ||salt */
+ memcpy(cmt_0_i_input + offset_salt, sig->salt, SALT_LENGTH_BYTES);
+
+ /* cmt_1_i_input is concat(seed,salt,round index) */
+ uint8_t cmt_1_i_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ memcpy(cmt_1_i_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t cmt_0[T][HASH_DIGEST_LENGTH] = {0};
+ uint8_t cmt_1[T][HASH_DIGEST_LENGTH] = {0};
+
+ FZ_ELEM eta_tilde[N];
+ FQ_ELEM u_tilde[N];
+
+ FQ_ELEM y_tilde[N] = {0};
+ FQ_ELEM s_tilde[N - K] = {0};
+
+ FQ_ELEM y[T][N];
+
+ int used_rsps = 0;
+ int is_signature_ok = 1;
+ for (uint16_t i = 0; i < T; i++) {
+
+ /* i+c */
+ uint16_t domain_sep_i = i + NUM_NODES_SEED_TREE;
+ /* i+c+dsc */
+ uint16_t domain_sep_idx_hash = domain_sep_i + HASH_CSPRNG_DOMAIN_SEP_CONST;
+
+ if (fixed_weight_b[i] == 1) {
+ memcpy(cmt_1_i_input,
+ rounds_seeds + SEED_LENGTH_BYTES * i,
+ SEED_LENGTH_BYTES);
+
+ cmt_1_i_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_1_i_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + 1] = domain_sep_idx_hash & 0xFF;
+ hash(cmt_1[i], cmt_1_i_input, sizeof(cmt_1_i_input));
+
+ /* CSPRNG is fed with concat(seed,salt,round index) represented
+ * as a 2 bytes little endian unsigned integer */
+ uint8_t csprng_input[CSPRNG_INPUT_LENGTH];
+ memcpy(csprng_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ memcpy(csprng_input, rounds_seeds + SEED_LENGTH_BYTES * i, SEED_LENGTH_BYTES);
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES] = (domain_sep_i >> 8) & 0xFF;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + 1] = domain_sep_i & 0xFF;
+
+ /* expand seed[i] into seed_e and seed_u */
+ initialize_csprng(&CSPRNG_state, csprng_input, CSPRNG_INPUT_LENGTH);
+ /* expand eta_tilde */
+ CSPRNG_zz_vec(eta_tilde, &CSPRNG_state);
+ /* expand u_tilde */
+ CSPRNG_fq_vec(u_tilde, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ fq_vec_by_restr_vec_scaled(y[i],
+ eta_tilde,
+ beta[i],
+ u_tilde);
+ fq_dz_norm(y[i]);
+ } else {
+ /* place y[i] in the buffer for later on hashing */
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fq_vec(y[i], sig->rsp_0[used_rsps].y);
+
+ FZ_ELEM sigma_local[N];
+ /*sigma is memcpy'ed directly into cmt_0 input buffer */
+ FZ_ELEM *sigma_ptr = cmt_0_i_input + DENSELY_PACKED_FQ_SYN_SIZE;
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fz_vec(sigma_local, sig->rsp_0[used_rsps].sigma);
+ memcpy(sigma_ptr,
+ &sig->rsp_0[used_rsps].sigma,
+ DENSELY_PACKED_FZ_VEC_SIZE);
+ is_signature_ok = is_signature_ok &&
+ is_zz_vec_in_restr_group(sigma_local);
+ memcpy(cmt_1[i], sig->rsp_1[used_rsps], HASH_DIGEST_LENGTH);
+ used_rsps++;
+
+ FQ_ELEM v[N];
+ convert_restr_vec_to_fq(v, sigma_local);
+ fq_vec_by_fq_vec_pointwise(y_tilde, v, y[i]);
+ fq_vec_by_fq_matrix(s_tilde, y_tilde, V_tr);
+ fq_dz_norm_synd(s_tilde);
+ FQ_ELEM to_compress[N - K];
+ fq_synd_minus_fq_vec_scaled(to_compress,
+ s_tilde,
+ beta[i],
+ pub_syn);
+ fq_dz_norm_synd(to_compress);
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_syn(cmt_0_i_input, to_compress);
+ cmt_0_i_input[offset_round_idx] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_0_i_input[offset_round_idx + 1] = domain_sep_idx_hash & 0xFF;
+
+ hash(cmt_0[i], cmt_0_i_input, sizeof(cmt_0_i_input));
+ }
+ } /* end for iterating on ZKID iterations */
+
+ /* PQClean-edit: remove assertion */
+ //assert(is_signature_ok);
+
+ uint8_t commit_digests[2][HASH_DIGEST_LENGTH];
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_merkle_tree_root_recompute(commit_digests[0],
+ cmt_0,
+ sig->mtp,
+ fixed_weight_b);
+ hash(commit_digests[1], (unsigned char *)cmt_1, sizeof(cmt_1));
+
+ uint8_t digest_01_recomputed[HASH_DIGEST_LENGTH];
+ hash(digest_01_recomputed,
+ (unsigned char *) commit_digests,
+ sizeof(commit_digests));
+
+ uint8_t digest_b_buf[T * DENSELY_PACKED_FQ_VEC_SIZE + HASH_DIGEST_LENGTH];
+ for (int x = 0; x < T; x++) {
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_vec(digest_b_buf + (x * DENSELY_PACKED_FQ_VEC_SIZE), y[x]);
+ }
+ memcpy(digest_b_buf + T * DENSELY_PACKED_FQ_VEC_SIZE, d_beta, HASH_DIGEST_LENGTH);
+
+ uint8_t digest_b_recomputed[HASH_DIGEST_LENGTH];
+ hash(digest_b_recomputed, digest_b_buf, sizeof(digest_b_buf));
+
+ int does_digest_01_match = ( memcmp(digest_01_recomputed,
+ sig->digest_01,
+ HASH_DIGEST_LENGTH) == 0);
+
+ /* PQClean-edit: remove assertion */
+ //assert(does_digest_01_match);
+
+ int does_digest_b_match = ( memcmp(digest_b_recomputed,
+ sig->digest_b,
+ HASH_DIGEST_LENGTH) == 0);
+
+ /* PQClean-edit: remove assertion */
+ //assert(does_digest_b_match);
+
+ is_signature_ok = is_signature_ok &&
+ does_digest_01_match &&
+ does_digest_b_match;
+ return is_signature_ok;
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/CROSS.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/CROSS.h
new file mode 100644
index 000000000..60742a9df
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/CROSS.h
@@ -0,0 +1,76 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+#pragma once
+
+#include
+
+#include "pack_unpack.h"
+#include "parameters.h"
+
+/* Public key: the parity check matrix is shrunk to a seed, syndrome
+ * represented in full */
+typedef struct {
+ uint8_t seed_pub[KEYPAIR_SEED_LENGTH_BYTES];
+ uint8_t s[DENSELY_PACKED_FQ_SYN_SIZE];
+} pubkey_t;
+
+/* Private key: just a single seed*/
+typedef struct {
+ uint8_t seed[KEYPAIR_SEED_LENGTH_BYTES];
+} prikey_t;
+
+typedef struct {
+ uint8_t y[DENSELY_PACKED_FQ_VEC_SIZE];
+ uint8_t sigma[DENSELY_PACKED_FZ_VEC_SIZE];
+} rsp_0_t;
+
+/* Signature: */
+typedef struct {
+ uint8_t salt[SALT_LENGTH_BYTES];
+ uint8_t digest_01[HASH_DIGEST_LENGTH];
+ uint8_t digest_b[HASH_DIGEST_LENGTH];
+ /*Seed tree paths storage*/
+ uint8_t stp[TREE_NODES_TO_STORE * SEED_LENGTH_BYTES];
+ /*Merkle tree proof field.*/
+ uint8_t mtp[HASH_DIGEST_LENGTH * TREE_NODES_TO_STORE];
+ rsp_0_t rsp_0[T - W];
+ uint8_t rsp_1[T - W][HASH_DIGEST_LENGTH];
+} CROSS_sig_t;
+
+/* keygen cannot fail */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CROSS_keygen(prikey_t *SK,
+ pubkey_t *PK);
+
+/* sign cannot fail */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CROSS_sign(const prikey_t *SK,
+ const char *m,
+ size_t mlen,
+ CROSS_sig_t *sig);
+
+/* verify returns 1 if signature is ok, 0 otherwise */
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CROSS_verify(const pubkey_t *PK,
+ const char *m,
+ size_t mlen,
+ const CROSS_sig_t *sig);
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/LICENSE b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/LICENSE
new file mode 100644
index 000000000..0e259d42c
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/LICENSE
@@ -0,0 +1,121 @@
+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/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/api.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/api.h
new file mode 100644
index 000000000..80f77b6fe
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/api.h
@@ -0,0 +1,80 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#ifndef PQCLEAN_CROSSRSDP128BALANCED_CLEAN_API_H
+#define PQCLEAN_CROSSRSDP128BALANCED_CLEAN_API_H
+
+#pragma once
+
+#include
+#include
+
+#define PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CRYPTO_ALGNAME "cross-rsdp-128-balanced"
+
+/* no. of bytes of the secret key */
+#define PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CRYPTO_SECRETKEYBYTES 32
+
+/* no. of bytes of the public key */
+#define PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CRYPTO_PUBLICKEYBYTES 77
+
+/* no. of bytes of overhead in a signed message */
+#define PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CRYPTO_BYTES 12912
+
+/* required bytes of input randomness */
+#define PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CRYPTO_RANDOMBYTES 16
+
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_keypair(unsigned char *pk,
+ unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign(unsigned char *sm,
+ size_t *smlen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_open(unsigned char *m,
+ size_t *mlen,
+ const unsigned char *sm,
+ size_t smlen,
+ const unsigned char *pk
+ );
+
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_signature(unsigned char *sig,
+ size_t *siglen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_verify(const unsigned char *sig,
+ size_t siglen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *pk
+ );
+
+#endif
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/csprng_hash.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/csprng_hash.c
new file mode 100644
index 000000000..56da4e442
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/csprng_hash.c
@@ -0,0 +1,82 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include
+
+#include "csprng_hash.h"
+
+#define POSITION_MASK (( (uint16_t)1 << BITS_TO_REPRESENT(T-1))-1)
+
+/* Fisher-Yates shuffle obtaining the entire required randomness in a single
+ * call */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_expand_digest_to_fixed_weight(uint8_t fixed_weight_string[T],
+ const uint8_t digest[HASH_DIGEST_LENGTH]) {
+ CSPRNG_STATE_T csprng_state;
+ initialize_csprng(&csprng_state,
+ (const unsigned char *) digest,
+ HASH_DIGEST_LENGTH);
+ uint8_t CSPRNG_buffer[ROUND_UP(BITS_CWSTR_RNG, 8) / 8];
+ csprng_randombytes(CSPRNG_buffer, ROUND_UP(BITS_CWSTR_RNG, 8) / 8, &csprng_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&csprng_state);
+
+ /* initialize CW string */
+ memset(fixed_weight_string, 1, W);
+ memset(fixed_weight_string + W, 0, T - W);
+
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ int pos_in_buf = 8;
+
+ int curr = 0;
+ while (curr < T) {
+ /* refill randomness buffer if needed */
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ /*we need to draw a number in 0... T-1-curr */
+ int bits_for_pos = BITS_TO_REPRESENT(T - 1 - curr);
+ uint64_t pos_mask = ( (uint64_t) 1 << bits_for_pos) - 1;
+ uint16_t candidate_pos = (sub_buffer & pos_mask);
+ if (candidate_pos < T - curr) {
+ int dest = curr + candidate_pos;
+ /* the position is admissible, swap */
+ uint8_t tmp = fixed_weight_string[curr];
+ fixed_weight_string[curr] = fixed_weight_string[dest];
+ fixed_weight_string[dest] = tmp;
+ curr++;
+ sub_buffer = sub_buffer >> bits_for_pos;
+ bits_in_sub_buf -= bits_for_pos;
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+} /* PQCLEAN_CROSSRSDP128BALANCED_CLEAN_expand_digest_to_fixed_weight */
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/csprng_hash.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/csprng_hash.h
new file mode 100644
index 000000000..c9c14549f
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/csprng_hash.h
@@ -0,0 +1,420 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+#pragma once
+
+#include "parameters.h"
+#include "sha3.h"
+
+/************************* CSPRNG ********************************/
+
+#define CSPRNG_STATE_T SHAKE_STATE_STRUCT
+/* initializes a CSPRNG, given the seed and a state pointer */
+static inline
+void initialize_csprng(CSPRNG_STATE_T *const csprng_state,
+ const unsigned char *const seed,
+ const uint32_t seed_len_bytes) {
+ // the second parameter is the security level of the SHAKE instance
+ xof_shake_init(csprng_state, SEED_LENGTH_BYTES * 8);
+ xof_shake_update(csprng_state, seed, seed_len_bytes);
+ xof_shake_final(csprng_state);
+} /* end initialize_csprng */
+
+/* extracts xlen bytes from the CSPRNG, given the state */
+static inline
+void csprng_randombytes(unsigned char *const x,
+ uint64_t xlen,
+ CSPRNG_STATE_T *const csprng_state) {
+ xof_shake_extract(csprng_state, x, xlen);
+}
+
+/* PQClean-edit: CSPRNG release context */
+static inline
+void csprng_release(CSPRNG_STATE_T *const csprng_state) {
+ xof_shake_release(csprng_state);
+}
+
+/**************** Parallel CSPRNG (x2, x3, x4) ***********************/
+
+#define CSPRNG_X2_STATE_T SHAKE_X2_STATE_STRUCT
+/* CRSPRNG_x3 calls SHAKE_x4 and discards the fourth input/output */
+#define CSPRNG_X3_STATE_T SHAKE_X4_STATE_STRUCT
+#define CSPRNG_X4_STATE_T SHAKE_X4_STATE_STRUCT
+
+/* initialize */
+static inline
+void initialize_csprng_x2(CSPRNG_X2_STATE_T *const csprng_state, const unsigned char *const seed1, const unsigned char *const seed2, const uint32_t seed_len_bytes) {
+ xof_shake_x2_init(csprng_state);
+ xof_shake_x2_update(csprng_state, seed1, seed2, seed_len_bytes);
+ xof_shake_x2_final(csprng_state);
+}
+static inline
+void initialize_csprng_x3(CSPRNG_X3_STATE_T *const csprng_state, const unsigned char *const seed1, const unsigned char *const seed2, const unsigned char *const seed3, const uint32_t seed_len_bytes) {
+ /* to perform xof_x3 it's faster to call xof_x4 and discard the last output */
+ xof_shake_x4_init(csprng_state);
+ xof_shake_x4_update(csprng_state, seed1, seed2, seed3, seed3, seed_len_bytes);
+ xof_shake_x4_final(csprng_state);
+}
+static inline
+void initialize_csprng_x4(CSPRNG_X4_STATE_T *const csprng_state, const unsigned char *const seed1, const unsigned char *const seed2, const unsigned char *const seed3, const unsigned char *const seed4, const uint32_t seed_len_bytes) {
+ xof_shake_x4_init(csprng_state);
+ xof_shake_x4_update(csprng_state, seed1, seed2, seed3, seed4, seed_len_bytes);
+ xof_shake_x4_final(csprng_state);
+}
+/* randombytes */
+static inline
+void csprng_randombytes_x2(unsigned char *const x1, unsigned char *const x2, uint64_t xlen, CSPRNG_X2_STATE_T *const csprng_state) {
+ xof_shake_x2_extract(csprng_state, x1, x2, xlen);
+}
+static inline
+void csprng_randombytes_x3(unsigned char *const x1, unsigned char *const x2, unsigned char *const x3, uint64_t xlen, CSPRNG_X3_STATE_T *const csprng_state) {
+ /* to perform xof_x3 it's faster to call xof_x4 and discard the last output */
+ xof_shake_x4_extract(csprng_state, x1, x2, x3, x3, xlen);
+}
+static inline
+void csprng_randombytes_x4(unsigned char *const x1, unsigned char *const x2, unsigned char *const x3, unsigned char *const x4, uint64_t xlen, CSPRNG_X4_STATE_T *const csprng_state) {
+ xof_shake_x4_extract(csprng_state, x1, x2, x3, x4, xlen);
+}
+/* release */
+static inline
+void csprng_release_x2(CSPRNG_X2_STATE_T *const csprng_state) {
+ xof_shake_x2_release(csprng_state);
+}
+static inline
+void csprng_release_x3(CSPRNG_X3_STATE_T *const csprng_state) {
+ xof_shake_x4_release(csprng_state);
+}
+static inline
+void csprng_release_x4(CSPRNG_X4_STATE_T *const csprng_state) {
+ xof_shake_x4_release(csprng_state);
+}
+
+/************** Single API for Parallel CSPRNG *******************/
+
+#define PAR_CSPRNG_STATE_T par_shake_ctx
+
+static inline
+void par_initialize_csprng(int par_level, PAR_CSPRNG_STATE_T *const states, const unsigned char *const seed1, const unsigned char *const seed2, const unsigned char *const seed3, const unsigned char *const seed4, const uint32_t seed_len_bytes) {
+ if (par_level == 1) {
+ initialize_csprng(&(states->state1), seed1, seed_len_bytes);
+ } else if (par_level == 2) {
+ initialize_csprng_x2(&(states->state2), seed1, seed2, seed_len_bytes);
+ } else if (par_level == 3) {
+ initialize_csprng_x3(&(states->state4), seed1, seed2, seed3, seed_len_bytes);
+ } else if (par_level == 4) {
+ initialize_csprng_x4(&(states->state4), seed1, seed2, seed3, seed4, seed_len_bytes);
+ }
+}
+static inline
+void par_csprng_randombytes(int par_level, PAR_CSPRNG_STATE_T *const states, unsigned char *const x1, unsigned char *const x2, unsigned char *const x3, unsigned char *const x4, uint64_t xlen) {
+ if (par_level == 1) {
+ csprng_randombytes(x1, xlen, &(states->state1));
+ } else if (par_level == 2) {
+ csprng_randombytes_x2(x1, x2, xlen, &(states->state2));
+ } else if (par_level == 3) {
+ csprng_randombytes_x3(x1, x2, x3, xlen, &(states->state4));
+ } else if (par_level == 4) {
+ csprng_randombytes_x4(x1, x2, x3, x4, xlen, &(states->state4));
+ }
+}
+static inline
+void par_csprng_release(int par_level, PAR_CSPRNG_STATE_T *const states) {
+ if (par_level == 1) {
+ csprng_release(&(states->state1));
+ } else if (par_level == 2) {
+ csprng_release_x2(&(states->state2));
+ } else if (par_level == 3) {
+ csprng_release_x3(&(states->state4));
+ } else if (par_level == 4) {
+ csprng_release_x4(&(states->state4));
+ }
+}
+
+/******************************************************************************/
+
+/* PQClean-edit: remove randombytes definition here to use PQClean randombytes */
+//static inline void randombytes(unsigned char * x, uint64_t xlen) ...
+
+/************************* HASH functions ********************************/
+
+/* Opaque algorithm agnostic hash call */
+static inline
+void hash(uint8_t digest[HASH_DIGEST_LENGTH],
+ const unsigned char *const m,
+ const uint64_t mlen) {
+ /* SHAKE with a 2*lambda bit digest is employed also for hashing */
+ CSPRNG_STATE_T csprng_state;
+ xof_shake_init(&csprng_state, SEED_LENGTH_BYTES * 8);
+ xof_shake_update(&csprng_state, m, mlen);
+ xof_shake_final(&csprng_state);
+ xof_shake_extract(&csprng_state, digest, HASH_DIGEST_LENGTH);
+ /* PQClean-edit: CSPRNG release context */
+ xof_shake_release(&csprng_state);
+}
+
+#define par_xof_input par_initialize_csprng
+#define par_xof_output par_csprng_randombytes
+#define par_xof_release par_csprng_release
+
+static inline
+void par_hash(
+ int par_level,
+ uint8_t digest_1[HASH_DIGEST_LENGTH],
+ uint8_t digest_2[HASH_DIGEST_LENGTH],
+ uint8_t digest_3[HASH_DIGEST_LENGTH],
+ uint8_t digest_4[HASH_DIGEST_LENGTH],
+ const unsigned char *const m_1,
+ const unsigned char *const m_2,
+ const unsigned char *const m_3,
+ const unsigned char *const m_4,
+ const uint64_t mlen) {
+ PAR_CSPRNG_STATE_T states;
+ par_xof_input(par_level, &states, m_1, m_2, m_3, m_4, mlen);
+ par_xof_output(par_level, &states, digest_1, digest_2, digest_3, digest_4, HASH_DIGEST_LENGTH);
+ par_xof_release(par_level, &states);
+}
+
+/********************** CSPRNG Sampling functions helpers ********************/
+
+static inline
+FQ_ELEM fq_star_rnd_state(CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_TO_REPRESENT(Q - 2) ) - 1;
+ FQ_ELEM rnd_value;
+ do {
+ csprng_randombytes((unsigned char *) &rnd_value,
+ sizeof(FQ_ELEM),
+ csprng_state);
+ rnd_value = mask & rnd_value;
+ } while (rnd_value > Q - 2);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(csprng_state);
+
+ return rnd_value + 1;
+} /* end fq_star_rnd_state */
+
+/***************** Specialized CSPRNGs for non binary domains *****************/
+
+/* CSPRNG sampling fixed weight strings */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_expand_digest_to_fixed_weight(uint8_t fixed_weight_string[T],
+ const uint8_t digest[HASH_DIGEST_LENGTH]);
+
+#define BITS_FOR_Q BITS_TO_REPRESENT(Q-1)
+#define BITS_FOR_Z BITS_TO_REPRESENT(Z-1)
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_FQ_VEC ((BITS_N_ZQ_CT_RNG - N*BITS_FOR_Q)* (BITS_FOR_Q-1))
+#define BUFSIZE_FQ_VEC (ROUND_UP(BITS_N_ZQ_CT_RNG+CORRECTION_FQ_VEC,8)/8)
+
+static inline
+void CSPRNG_fq_vec(FQ_ELEM res[N],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_FOR_Q) - 1;
+ /* NOTE: Current bit cost estimation technique underestimates the failures
+ * whenever they appear in a run; an upper bound on the bit-cost is considering
+ * the failures to be discarding the entire value, instead of a single bit.
+ * The following correction factor takes this into account */
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_N_ZQ_CT_RNG - N*BITS_FOR_Q)* (BITS_FOR_Q-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_N_ZQ_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_FQ_VEC];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right, shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_FQ_VEC, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+ while (placed < N) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ res[placed] = sub_buffer & mask;
+ if (res[placed] < Q) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Q;
+ bits_in_sub_buf -= BITS_FOR_Q;
+
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
+
+#define BITS_FOR_Q_M_ONE BITS_TO_REPRESENT(Q-2)
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_FQ_VEC_BETA ((BITS_BETA_ZQSTAR_CT_RNG - T*BITS_FOR_Q_M_ONE) * (BITS_FOR_Q_M_ONE-1))
+#define BUFSIZE_FQ_VEC_BETA (ROUND_UP(BITS_BETA_ZQSTAR_CT_RNG+CORRECTION_FQ_VEC_BETA,8)/8)
+
+static inline
+void CSPRNG_fq_vec_beta(FQ_ELEM res[T],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_FOR_Q_M_ONE) - 1;
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_BETA_ZQSTAR_CT_RNG - T*BITS_FOR_Q_M_ONE) * (BITS_FOR_Q_M_ONE-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_BETA_ZQSTAR_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_FQ_VEC_BETA];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right , shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_FQ_VEC_BETA, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+ while (placed < T) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ /* draw from 0 ... Q-2, then add 1*/
+ res[placed] = (sub_buffer & mask) + 1;
+ if (res[placed] < Q) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Q_M_ONE;
+ bits_in_sub_buf -= BITS_FOR_Q_M_ONE;
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_FQ_MAT ((BITS_V_CT_RNG - K*(N-K)*BITS_FOR_Q) * (BITS_FOR_Q-1))
+#define BUFSIZE_FQ_MAT (ROUND_UP(BITS_V_CT_RNG+CORRECTION_FQ_MAT,8)/8)
+
+static inline
+void CSPRNG_fq_mat(FQ_ELEM res[K][N - K],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_FOR_Q) - 1;
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_V_CT_RNG - K*(N-K)*BITS_FOR_Q) * (BITS_FOR_Q-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_V_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_FQ_MAT];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right , shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_FQ_MAT, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+
+ while (placed < K * (N - K)) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ *( (FQ_ELEM *)res + placed) = sub_buffer & mask;
+ if (*( (FQ_ELEM *)res + placed) < Q) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Q;
+ bits_in_sub_buf -= BITS_FOR_Q;
+
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_ZZ_VEC ((BITS_N_ZZ_CT_RNG - N*BITS_FOR_Z) * (BITS_FOR_Z-1))
+#define BUFSIZE_ZZ_VEC ROUND_UP(BITS_N_ZZ_CT_RNG+CORRECTION_ZZ_VEC,8)/8
+
+static inline
+void CSPRNG_zz_vec(FZ_ELEM res[N],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FZ_ELEM mask = ( (FZ_ELEM) 1 << BITS_FOR_Z) - 1;
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_N_ZZ_CT_RNG - N*BITS_FOR_Z) * (BITS_FOR_Z-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_N_ZZ_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_ZZ_VEC];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right , shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_ZZ_VEC, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+ while (placed < N) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ /* get */
+ res[placed] = sub_buffer & mask;
+ if (res[placed] < Z) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Z;
+ bits_in_sub_buf -= BITS_FOR_Z;
+
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/fq_arith.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/fq_arith.h
new file mode 100644
index 000000000..4cbcf6796
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/fq_arith.h
@@ -0,0 +1,142 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include
+#include
+
+#include "csprng_hash.h"
+#include "parameters.h"
+#include "restr_arith.h"
+
+#define NUM_BITS_Q (BITS_TO_REPRESENT(Q))
+
+#define FQRED_SINGLE(x) (((x) & 0x7F) + ((x) >> 7))
+#define FQRED_DOUBLE(x) FQRED_SINGLE(FQRED_SINGLE(x))
+#define FQRED_OPPOSITE(x) ((x) ^ 0x7F)
+#define FQ_DOUBLE_ZERO_NORM(x) (((x) + (((x) + 1) >> 7)) & 0x7F)
+#define RESTR_TO_VAL(x) ( (FQ_ELEM) (RESTR_G_TABLE >> (8*(uint64_t)(x))) )
+
+/* in-place normalization of redundant zero representation for syndromes*/
+static inline
+void fq_dz_norm_synd(FQ_ELEM v[N - K]) {
+ for (int i = 0; i < N - K; i++) {
+ v[i] = FQ_DOUBLE_ZERO_NORM(v[i]);
+ }
+}
+
+static inline
+void fq_dz_norm(FQ_ELEM v[N]) {
+ for (int i = 0; i < N; i++) {
+ v[i] = FQ_DOUBLE_ZERO_NORM(v[i]);
+ }
+}
+/* computes the product e*H of an n-element restricted vector by a (n-k)*n
+ * F_q H is in systematic form. Only the non systematic portion of H =[V I],
+ * V, is provided, transposed, hence linearized by columns so that syndrome
+ * computation is vectorizable. */
+
+static
+void restr_vec_by_fq_matrix(FQ_ELEM res[N - K],
+ const FZ_ELEM e[N],
+ FQ_ELEM V_tr[K][N - K]) {
+ for (int i = K ; i < N; i++) {
+ res[i - K] = RESTR_TO_VAL(e[i]);
+ }
+ for (int i = 0; i < K; i++) {
+ for (int j = 0; j < N - K; j++) {
+ res[j] = FQRED_DOUBLE( (FQ_DOUBLEPREC) res[j] +
+ (FQ_DOUBLEPREC) RESTR_TO_VAL(e[i]) *
+ (FQ_DOUBLEPREC) V_tr[i][j]);
+ }
+ }
+}
+
+static
+void fq_vec_by_fq_matrix(FQ_ELEM res[N - K],
+ const FQ_ELEM e[N],
+ FQ_ELEM V_tr[K][N - K]) {
+ memcpy(res, e + K, (N - K)*sizeof(FQ_ELEM));
+ for (int i = 0; i < K; i++) {
+ for (int j = 0; j < N - K; j++) {
+ res[j] = FQRED_DOUBLE( (FQ_DOUBLEPREC) res[j] +
+ (FQ_DOUBLEPREC) e[i] *
+ (FQ_DOUBLEPREC) V_tr[i][j]);
+ }
+ }
+}
+
+static inline
+void fq_vec_by_fq_vec_pointwise(FQ_ELEM res[N],
+ const FQ_ELEM in1[N],
+ const FQ_ELEM in2[N]) {
+ for (int i = 0; i < N; i++) {
+ res[i] = FQRED_DOUBLE( (FQ_DOUBLEPREC) in1[i] *
+ (FQ_DOUBLEPREC) in2[i] );
+ }
+}
+
+static inline
+void restr_by_fq_vec_pointwise(FQ_ELEM res[N],
+ const FZ_ELEM in1[N],
+ const FQ_ELEM in2[N]) {
+ for (int i = 0; i < N; i++) {
+ res[i] = FQRED_DOUBLE( (FQ_DOUBLEPREC) RESTR_TO_VAL(in1[i]) *
+ (FQ_DOUBLEPREC) in2[i]);
+ }
+}
+
+/* e*beta + u_tilde*/
+static inline
+void fq_vec_by_restr_vec_scaled(FQ_ELEM res[N],
+ const FZ_ELEM e[N],
+ const FQ_ELEM beta,
+ const FQ_ELEM u_tilde[N]) {
+ for (int i = 0; i < N; i++) {
+ res[i] = FQRED_DOUBLE( (FQ_DOUBLEPREC) u_tilde[i] +
+ (FQ_DOUBLEPREC) RESTR_TO_VAL(e[i]) * (FQ_DOUBLEPREC) beta) ;
+ }
+}
+
+static inline
+void fq_synd_minus_fq_vec_scaled(FQ_ELEM res[N - K],
+ const FQ_ELEM synd[N - K],
+ const FQ_ELEM beta,
+ const FQ_ELEM s[N - K]) {
+ for (int j = 0; j < N - K; j++) {
+ FQ_ELEM tmp = FQRED_DOUBLE( (FQ_DOUBLEPREC) s[j] * (FQ_DOUBLEPREC) beta);
+ tmp = FQ_DOUBLE_ZERO_NORM(tmp);
+ res[j] = FQRED_SINGLE( (FQ_DOUBLEPREC) synd[j] + FQRED_OPPOSITE(tmp) );
+ }
+}
+
+static inline
+void convert_restr_vec_to_fq(FQ_ELEM res[N],
+ const FZ_ELEM in[N]) {
+ for (int j = 0; j < N; j++) {
+ res[j] = RESTR_TO_VAL(in[j]);
+ }
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/merkle.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/merkle.c
new file mode 100644
index 000000000..48b0e1dc8
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/merkle.c
@@ -0,0 +1,344 @@
+/*
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (May 2023)
+ *
+ * @author: Patrick Karl
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+#include
+
+#include "merkle.h"
+
+#define LEAVES_FULL_TREE(L) ( (1UL << LOG2(L) ) )
+#define LEAVES_HALF_TREE(L) ( (LEAVES_FULL_TREE(L) >> 1) )
+
+#define PARENT(i) ( ((i)%2) ? (((i)-1)/2) : (((i)-2)/2) )
+#define RIGHT_CHILD(i) ( (2*(i)+2) )
+#define LEFT_CHILD(i) ( (2*(i)+1) )
+#define SIBLING(i) ( ((i)%2) ? (i)+1 : (i)-1 )
+
+#define RL(i) ((i)==1 ? r_node : l_node)
+#define OFFSET(i) ( (i)*HASH_DIGEST_LENGTH )
+
+#define CHALLENGE_PROOF_VALUE 0
+#define INVALID_MERKLE_NODE 0
+#define VALID_MERKLE_NODE 1
+
+#define NOT_COMPUTED 0
+#define COMPUTED 1
+
+/*
+ * setup_tree()
+ *
+ * uint16_t layer_offset[LOG2(T)+1] : Stores one offset per layer for layer change.
+ * Required for the computation of PARENT and CHILD nodes.
+ * uint16_t nodes_per_layer[LOG2(T)+1] : Stores the numbers of nodes used in the truncated Merkle tree.
+ */
+static
+void setup_tree(uint16_t layer_offsets[LOG2(T) + 1],
+ uint16_t nodes_per_layer[LOG2(T) + 1]) {
+ uint32_t depth, layer;
+ uint32_t r_leaves;
+ int subtree_found;
+
+ /* Initialize array with full node counts */
+ for (size_t i = 0; i < LOG2(T) + 1; i++) {
+ layer_offsets[i] = (1UL << i);
+ }
+
+ /* Count root node */
+ layer = 0;
+ layer_offsets[layer] -= 1;
+
+ /* Count left tree nodes (always full) */
+ for (size_t i = 1; i < LOG2(T) + 1; i++) {
+ layer_offsets[i] -= (1UL << (i - 1));
+ }
+
+ /* Check every full subtree on right side and subtract missing nodes */
+ r_leaves = T - (1UL << (LOG2(T) - 1));
+ layer = 1;
+ while (r_leaves > 0) {
+ depth = 0;
+ subtree_found = 0;
+ while ( !subtree_found ) {
+ if (r_leaves <= (1UL << depth)) {
+ for (int i = depth; i > 0; i--) {
+ layer_offsets[layer + i] -= (1UL << (i - 1));
+ }
+ r_leaves -= LEAVES_HALF_TREE(r_leaves);
+ layer_offsets[layer] -= 1;
+ layer++;
+ subtree_found = 1;
+ } else {
+ depth++;
+ }
+ }
+ }
+
+ /* For the offset, subtract all missing nodes from previous layers from current layer */
+ for (int i = LOG2(T); i >= 0; i--) {
+ nodes_per_layer[i] = (1UL << i) - layer_offsets[i];
+ for (int j = i - 1; j >= 0; j--) {
+ layer_offsets[i] -= layer_offsets[j];
+ }
+ layer_offsets[i] >>= 1;
+ }
+}
+
+/*
+ * get_leaf_indices() is quite similar to setup_tree(), however requires the
+ * offset values to compute the correct indices.
+ *
+ * uint16_t merkle_leaf_indices[T] : Stores the indices in the truncated tree
+ * where the leaves are placed.
+ * uint16_t layer_offsets[LOG2(T)+1] : Same as above.
+ */
+static
+void get_leaf_indices(uint16_t merkle_leaf_indices[T],
+ const uint16_t layer_offsets[LOG2(T) + 1]) {
+ uint32_t r_leaves;
+ uint32_t idx_ctr = 0;
+
+ /* r_node: current root node of next subtree, will always be right-child of previous root */
+ /* l_node: traverses from current root node to left-childs until depth of subtree is found */
+ uint32_t r_node, l_node;
+ uint32_t layer, depth, subtree_found;
+
+ /* If tree is already balanced, simply copy leaves to corresponding position */
+ if (T == (1UL << LOG2(T))) {
+ for (size_t i = 0; i < T; i++) {
+ merkle_leaf_indices[i] = T - 1 + i;
+ }
+ return;
+ }
+
+ /* Create (un-) balanced Merkle tree */
+ r_leaves = T;
+ depth = 0;
+ layer = 0;
+ r_node = 0;
+ l_node = LEFT_CHILD(r_node) - 2 * layer_offsets[layer + depth];
+ while (r_leaves > 0) {
+ depth = 1;
+ subtree_found = 0;
+ /* Start from the current root node r_node until the size of a full left-subtree is found. */
+ /* If only one leaf is remaining, put it to current root-node, macro RL() is used to decide that. */
+ while ( !subtree_found ) {
+ if (r_leaves <= (1UL << depth)) {
+ for (size_t j = 0; j < LEAVES_HALF_TREE(r_leaves); j++) {
+ merkle_leaf_indices[idx_ctr++] = RL(r_leaves) + j;
+ }
+ r_node = RIGHT_CHILD(r_node) - 2 * layer_offsets[layer];
+ l_node = LEFT_CHILD(r_node) - 2 * layer_offsets[layer];
+ layer++;
+ r_leaves -= LEAVES_HALF_TREE(r_leaves);
+ subtree_found = 1;
+ } else {
+ l_node = LEFT_CHILD(l_node) - 2 * layer_offsets[layer + depth];
+ depth++;
+ }
+ }
+ }
+}
+
+/* PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generate_merkle_tree()
+ *
+ * unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH] :
+ * stores the hashes of the associated tree nodes.
+ * const unsigned char commitments[T][HASH_DIGEST_LENGTH] : Contains the
+ * hashed commitments that build the tree.
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generate_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE *
+ HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH]) {
+ size_t i;
+ uint32_t node_ctr, parent_layer;
+
+ uint16_t merkle_leaf_indices[T];
+ uint16_t layer_offsets[LOG2(T) + 1];
+ uint16_t nodes_per_layer[LOG2(T) + 1];
+
+ /* Setup the tree to get offsets for the computation of PARENT/CHILD nodes, as well as the number of nodes per layer */
+ /* Move leafs in correct positions of the unbalanced Merkle tree */
+ setup_tree(layer_offsets, nodes_per_layer);
+ get_leaf_indices(merkle_leaf_indices, layer_offsets);
+
+ /* Place commitments on the leaves indicated by merkle_leaf_indices */
+ for (i = 0; i < T; i++) {
+ memcpy(merkle_tree + merkle_leaf_indices[i]*HASH_DIGEST_LENGTH,
+ commitments + i,
+ HASH_DIGEST_LENGTH);
+ }
+
+ /* Hash the child nodes */
+ node_ctr = 0;
+ parent_layer = LOG2(T) - 1;
+ for (i = NUM_NODES_MERKLE_TREE - 1; i > 0; i -= 2) {
+ hash(merkle_tree + OFFSET(PARENT(i) + layer_offsets[parent_layer]), merkle_tree + OFFSET(SIBLING(i)), 2 * HASH_DIGEST_LENGTH);
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ }
+}
+
+/* PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generate_merkle_proof()
+ *
+ * uint16_t merkle_proof_indices[TREE_NODES_TO_STORE] : stores the sorted indices required for the proof.
+ * uint16_t merkle_proof_len : Actual length of the proof. Can vary depending on the challenge.
+ * const unsigned char challenge : Challenge that indicated which nodes will be recomputed by the verifier.
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generate_merkle_proof(uint16_t merkle_proof_indices[TREE_NODES_TO_STORE],
+ uint16_t *merkle_proof_len,
+ const unsigned char challenge[T]) {
+ unsigned char flag_tree[NUM_NODES_MERKLE_TREE] = {NOT_COMPUTED};
+ uint32_t node_ctr, parent_layer;
+ size_t i;
+
+ uint16_t layer_offsets[LOG2(T) + 1];
+ uint16_t nodes_per_layer[LOG2(T) + 1];
+ uint16_t merkle_leaf_indices[T];
+
+ /* Setup the tree to get offsets for the computation of PARENT/CHILD nodes, as well as the number of nodes per layer */
+ setup_tree(layer_offsets, nodes_per_layer);
+ get_leaf_indices(merkle_leaf_indices, layer_offsets);
+
+ /* Use challenges to mark nodes of path tree */
+ for (size_t j = 0; j < T; j++) {
+ if (challenge[j] == CHALLENGE_PROOF_VALUE) {
+ flag_tree[merkle_leaf_indices[j]] = COMPUTED;
+ }
+ }
+
+ /* Loop over all nodes, starting at the leaves */
+ /* If at least one sibling is marked as COMPUTED, also mark the PARENT as such */
+ /* Only add sibling of COMPUTED sibling as proof node if not both of them are marked as COMPUTED. */
+ node_ctr = 0;
+ parent_layer = LOG2(T) - 1;
+ *merkle_proof_len = 0;
+ for (i = NUM_NODES_MERKLE_TREE - 1; i > 0; i -= 2) {
+
+ flag_tree[PARENT(i) + layer_offsets[parent_layer]] = (flag_tree[i] == COMPUTED) || (flag_tree[SIBLING(i)] == COMPUTED);
+
+ /* Add left sibling only if left one was computed */
+ if ( (flag_tree[i] == COMPUTED) && (flag_tree[SIBLING(i)] == NOT_COMPUTED) ) {
+ merkle_proof_indices[(*merkle_proof_len)++] = SIBLING(i);
+ }
+
+ /* Add right sibling only right was computed */
+ if ( (flag_tree[i] == NOT_COMPUTED) && (flag_tree[SIBLING(i)] == COMPUTED) ) {
+ merkle_proof_indices[(*merkle_proof_len)++] = i;
+ }
+
+ /* Due to the unbalenced structure we got to keep track of the nodes per layer processed */
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ }
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_rebuild_merkle_tree()
+ *
+ * unsigned char merkle_tree[NUM_NODES_MERKLE_TREE*HASH_DIGEST_LENGTH] : Stores the Hashes of the recomputed Merkle tree.
+ * const unsigned char merkle_proof[TREE_NODES_TO_STORE] : Merkle proof containing the nodes required for recomputation.
+ * const unsigned char commitments[T][HASH_DIGEST_LENGTH] : Stores the commitments.
+ * const unsigned char challenge[T] : Challenge vector to indicate the computed commitments.
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_rebuild_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ const unsigned char merkle_proof[TREE_NODES_TO_STORE * HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH],
+ const unsigned char challenge[T]) {
+ uint16_t flag_tree_valid[NUM_NODES_MERKLE_TREE] = {INVALID_MERKLE_NODE};
+
+ uint16_t merkle_leaf_indices[T];
+ uint16_t layer_offsets[LOG2(T) + 1];
+ uint16_t nodes_per_layer[LOG2(T) + 1];
+
+ uint16_t ctr;
+ uint32_t node_ctr, parent_layer;
+ size_t i;
+
+ /* Input consists of hash digests stored at child nodes and the index of the parent node for domain separation */
+ unsigned char hash_input[2 * HASH_DIGEST_LENGTH];
+
+ /* Move leafs in correct positions of binary merkle tree */
+ /* Setup the tree again, computing the offsets and from that, the leaf indices */
+ setup_tree(layer_offsets, nodes_per_layer);
+ get_leaf_indices(merkle_leaf_indices, layer_offsets);
+
+ /* Copy the commitments to the positions indicated by the challenge */
+ for (i = 0; i < T; i++) {
+ if (challenge[i] == CHALLENGE_PROOF_VALUE) {
+ flag_tree_valid[merkle_leaf_indices[i]] = VALID_MERKLE_NODE;
+ memcpy(merkle_tree + merkle_leaf_indices[i]*HASH_DIGEST_LENGTH, commitments + i, HASH_DIGEST_LENGTH);
+ }
+ }
+ /* Create hash tree by hashing valid leaf nodes */
+ ctr = 0;
+ node_ctr = 0;
+ parent_layer = LOG2(T) - 1;
+ for (i = NUM_NODES_MERKLE_TREE - 1; i > 0; i -= 2) {
+
+ /* Both siblings are unused, but it must be kept track of the node and layer counter to chose the right offsets */
+ if (flag_tree_valid[i] == INVALID_MERKLE_NODE && flag_tree_valid[SIBLING(i)] == INVALID_MERKLE_NODE) {
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ continue;
+ }
+
+ /* Prepare input to hash */
+ /* Process right sibling from the tree if valid, otherwise take it from the merkle proof */
+ if (flag_tree_valid[i] == VALID_MERKLE_NODE) {
+ memcpy(hash_input + HASH_DIGEST_LENGTH, merkle_tree + OFFSET(i), HASH_DIGEST_LENGTH);
+ } else {
+ memcpy(hash_input + HASH_DIGEST_LENGTH, merkle_proof + OFFSET(ctr), HASH_DIGEST_LENGTH);
+ ctr++;
+ }
+
+ /* Process left sibling from the tree if valid, otherwise take it from the merkle proof */
+ if (flag_tree_valid[SIBLING(i)] == VALID_MERKLE_NODE) {
+ memcpy(hash_input, merkle_tree + OFFSET(SIBLING(i)), HASH_DIGEST_LENGTH);
+ } else {
+ memcpy(hash_input, merkle_proof + OFFSET(ctr), HASH_DIGEST_LENGTH);
+ ctr++;
+ }
+
+ /* Hash it and store the digest at the parent node */
+ hash(merkle_tree + OFFSET(PARENT(i) + layer_offsets[parent_layer]), hash_input, 2 * HASH_DIGEST_LENGTH);
+ flag_tree_valid[PARENT(i) + layer_offsets[parent_layer]] = VALID_MERKLE_NODE;
+
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ }
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/merkle.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/merkle.h
new file mode 100644
index 000000000..27b55a90f
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/merkle.h
@@ -0,0 +1,41 @@
+/*
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (May 2023)
+ *
+ * @author: Patrick Karl
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "csprng_hash.h"
+#include "parameters.h"
+
+/***********************************************************************************************/
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generate_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH]);
+
+/***********************************************************************************************/
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generate_merkle_proof(uint16_t merkle_proof_indices[TREE_NODES_TO_STORE],
+ uint16_t *merkle_proof_len,
+ const unsigned char challenge[T]);
+
+/***********************************************************************************************/
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_rebuild_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ const unsigned char merkle_proof[TREE_NODES_TO_STORE * HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH],
+ const unsigned char challenge[T]);
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/merkle_tree.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/merkle_tree.h
new file mode 100644
index 000000000..b0d1fca2e
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/merkle_tree.h
@@ -0,0 +1,83 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author: Patrick Karl
+ * @author Gerardo Pelosi
+ *
+ * Authors listed in lexicographic order.
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "csprng_hash.h"
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_merkle_tree_root_compute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ uint8_t leaves[T][HASH_DIGEST_LENGTH]);
+uint16_t PQCLEAN_CROSSRSDP128BALANCED_CLEAN_merkle_tree_proof_compute(uint8_t mtp[HASH_DIGEST_LENGTH * TREE_NODES_TO_STORE],
+ const uint8_t tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ const uint8_t leaves_to_reveal[T]);
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_merkle_tree_root_recompute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t recomputed_leaves[T][HASH_DIGEST_LENGTH],
+ const uint8_t mtp[HASH_DIGEST_LENGTH * TREE_NODES_TO_STORE],
+ const uint8_t leaves_to_reveal[T]);
+
+#include "merkle.h"
+/* Stub of the interface to Merkle tree root computer from all leaves */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_merkle_tree_root_compute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ /* input, although mutable in caller, having as const is non
+ * tolerated in strict ISO C */
+ uint8_t leaves[T][HASH_DIGEST_LENGTH]) {
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generate_merkle_tree(tree, leaves);
+ /* Root is at first position of the tree */
+ memcpy(root, tree, HASH_DIGEST_LENGTH);
+}
+
+/* Stub interface to the function computing the Merkle tree proof, storing it
+ * in the signature. Returns the number of digests in the merkle tree proof */
+uint16_t PQCLEAN_CROSSRSDP128BALANCED_CLEAN_merkle_tree_proof_compute(uint8_t mtp[HASH_DIGEST_LENGTH * TREE_NODES_TO_STORE],
+ const uint8_t tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ const uint8_t leaves_to_reveal[T]) {
+ uint16_t mtp_len;
+ uint16_t merkle_proof_indices[TREE_NODES_TO_STORE];
+
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generate_merkle_proof(merkle_proof_indices, &mtp_len, leaves_to_reveal);
+
+ for (size_t i = 0; i < mtp_len; i++) {
+ memcpy(mtp + i * HASH_DIGEST_LENGTH, tree + merkle_proof_indices[i]*HASH_DIGEST_LENGTH,
+ HASH_DIGEST_LENGTH);
+ }
+ return mtp_len;
+}
+
+/* stub of the interface to Merkle tree recomputation given the proof and
+ * the computed leaves */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_merkle_tree_root_recompute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t recomputed_leaves[T][HASH_DIGEST_LENGTH],
+ const uint8_t mtp[HASH_DIGEST_LENGTH * TREE_NODES_TO_STORE],
+ const uint8_t leaves_to_reveal[T]) {
+
+ unsigned char tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH];
+
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_rebuild_merkle_tree(tree, mtp, recomputed_leaves, leaves_to_reveal);
+ memcpy(root, tree, HASH_DIGEST_LENGTH);
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/pack_unpack.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/pack_unpack.c
new file mode 100644
index 000000000..a038e9bfd
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/pack_unpack.c
@@ -0,0 +1,618 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Jonas Schupp
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include
+#include
+
+#include "pack_unpack.h"
+
+/*Implementation of packing of 1 to 16 bits value vectors in 8 bit vectors,
+ * generic inputs from 1 to 16 bit possible*/
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_vec()
+ *
+ * uint8_t out[DENSELY_PACKED_FQ_VEC_SIZE] : FQ packed in bytes
+ * const FQ_ELEM in[N] : FQ Vec input, to be packed
+ *
+ * This function handles the packing of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_vec(uint8_t out[DENSELY_PACKED_FQ_VEC_SIZE],
+ const FQ_ELEM in[N]) {
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_pack_fq(out, in, DENSELY_PACKED_FQ_VEC_SIZE, N);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_syn()
+ *
+ * uint8_t out[DENSELY_PACKED_FQ_SYN_SIZE] : FQ packed in bytes
+ * const FQ_ELEM in[N-K] : FQ Vec input, to be packed
+ *
+ * This function handles the packing of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_syn(uint8_t out[DENSELY_PACKED_FQ_SYN_SIZE],
+ const FQ_ELEM in[N - K]) {
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_pack_fq(out, in, DENSELY_PACKED_FQ_SYN_SIZE, N - K);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fz_vec()
+ *
+ * uint8_t out[DENSELY_PACKED_FZ_VEC_SIZE] : FQ packed in bytes
+ * const FZ_ELEM in[N] : FQ Vec input, to be packed
+ *
+ * This function handles the packing of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fz_vec(uint8_t out[DENSELY_PACKED_FZ_VEC_SIZE],
+ const FZ_ELEM in[N]) {
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_pack_fz(out, in, DENSELY_PACKED_FZ_VEC_SIZE, N);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fz_rsdp_g_vec()
+ *
+ * uint8_t out[DENSELY_PACKED_FZ_RSDP_G_VEC_SIZE] : Zz packed in bytes
+ * const FZ_ELEM in[M] : Zz Vec input, to be packed
+ *
+ * This function handles the packing of the add. rdsp(g) vector in Zz
+ */
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_pack_fq()
+ *
+ * uint8_t *out : FQ packed in bytes
+ * const FQ_ELEM *in : FQ Vec input, to be packed
+ * size_t outlen : Length of out
+ * size_t in : Length of in
+ *
+ * This function handles the packing of an vector of el. in FQ of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_pack_fq(uint8_t *out, const FQ_ELEM *in,
+ const size_t outlen, const size_t inlen) {
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen / 8; i++) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] |= (in[i * 8 + 4] << 5) | (in[i * 8 + 5] >> 2);
+ out[i * 7 + 5] |= (in[i * 8 + 5] << 6) | (in[i * 8 + 6] >> 1);
+ out[i * 7 + 6] |= (in[i * 8 + 6] << 7) | (in[i * 8 + 7]);
+ }
+ const uint8_t n_remainder = inlen % 8;
+ if (n_remainder == 1) {
+ out[i * 7] = (in[i * 8] << 1);
+ } else if (n_remainder == 2) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] = (in[i * 8 + 1] << 2);
+ } else if (n_remainder == 3) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] = (in[i * 8 + 2] << 3);
+ } else if (n_remainder == 4) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4);
+ } else if (n_remainder == 5) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] = (in[i * 8 + 4] << 5);
+ } else if (n_remainder == 6) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] |= (in[i * 8 + 4] << 5) | (in[i * 8 + 5] >> 2);
+ out[i * 7 + 5] = (in[i * 8 + 5] << 6);
+ } else if (n_remainder == 7) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] |= (in[i * 8 + 4] << 5) | (in[i * 8 + 5] >> 2);
+ out[i * 7 + 5] |= (in[i * 8 + 5] << 6) | (in[i * 8 + 6] >> 1);
+ out[i * 7 + 6] |= (in[i * 8 + 6] << 7);
+ }
+
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_pack_fz()
+ *
+ * uint8_t *out : Zz packed in bytes
+ * const FZ_ELEM *in : Zz Vec input, to be packed
+ * size_t outlen : Length of out
+ * size_t in : Length of in
+ *
+ * This function handles the packing of an vector of el. in Zz of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_pack_fz(uint8_t *out, const FZ_ELEM *in, const size_t outlen, const size_t inlen) {
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen / 8; i++) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ out[i * 3 + 1] |= (in[i * 8 + 5] >> 2);
+ out[i * 3 + 2] = (in[i * 8 + 5] << 6);
+ out[i * 3 + 2] |= (in[i * 8 + 6] << 3);
+ out[i * 3 + 2] |= (in[i * 8 + 7]);
+ }
+ const uint8_t n_remainder = inlen % 8;
+ if (n_remainder == 1) {
+ out[i * 3] = (in[i * 8] << 5);
+ } else if (n_remainder == 2) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ } else if (n_remainder == 3) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ } else if (n_remainder == 4) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ } else if (n_remainder == 5) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ } else if (n_remainder == 6) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ out[i * 3 + 1] |= (in[i * 8 + 5] >> 2);
+ out[i * 3 + 2] = (in[i * 8 + 5] << 6);
+ } else if (n_remainder == 7) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ out[i * 3 + 1] |= (in[i * 8 + 5] >> 2);
+ out[i * 3 + 2] = (in[i * 8 + 5] << 6);
+ out[i * 3 + 2] |= (in[i * 8 + 6] << 3);
+ }
+
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fq_vec()
+ *
+ * FQ_ELEM out[N] : FQ Vec output
+ * const uint8_t in[DENSELY_PACKED_FQ_VEC_SIZE] : FQ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fq_vec(FQ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FQ_VEC_SIZE]) {
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_unpack_fq(out, in, N, DENSELY_PACKED_FQ_VEC_SIZE);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fq_syn()
+ *
+ * FQ_ELEM out[N] : FQ Vec output
+ * const uint8_t in[DENSELY_PACKED_FQ_SYN_SIZE] : FQ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fq_syn(FQ_ELEM out[N - K],
+ const uint8_t in[DENSELY_PACKED_FQ_SYN_SIZE]) {
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_unpack_fq(out, in, N - K, DENSELY_PACKED_FQ_SYN_SIZE);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fz_vec()
+ *
+ * FZ_ELEM out[N] : FQ Vec output
+ * const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE] : FQ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fz_vec(FZ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE]) {
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_unpack_fz(out, in, N);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fz_rsdp_g_vec()
+ *
+ * FZ_ELEM out[M] : FZ Vec output
+ * const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE] : FZ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_unpack_fq()
+ *
+ * FQ_ELEM *out : FQ output, unpacked
+ * const uint8_t *in : FQ Vec input, packed in bytes
+ * size_t outlen : Length of out
+ * size_t in : Length of in
+ *
+ * This function unpacks an vector of el. in FQ of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_unpack_fq(FQ_ELEM *out, const uint8_t *in,
+ size_t outlen, size_t inlen) {
+
+ /* PQClean-edit: unused parameter */
+ (void)inlen;
+
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen / 8; i++) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ out[i * 8 + 5] = ((in[i * 7 + 4] << 2) & 0x7F);
+ out[i * 8 + 5] |= (in[i * 7 + 5] >> 6);
+ out[i * 8 + 6] = ((in[i * 7 + 5] << 1) & 0x7F);
+ out[i * 8 + 6] |= (in[i * 7 + 6] >> 7);
+ out[i * 8 + 7] = (in[i * 7 + 6] & 0x7F);
+ }
+ const uint8_t n_remainder = outlen % 8;
+ if (n_remainder == 1) {
+ out[i * 8] = (in[i * 7] >> 1);
+ } else if (n_remainder == 2) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ } else if (n_remainder == 3) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ } else if (n_remainder == 4) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ } else if (n_remainder == 5) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ } else if (n_remainder == 6) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ out[i * 8 + 5] = ((in[i * 7 + 4] << 2) & 0x7F);
+ out[i * 8 + 5] |= (in[i * 7 + 5] >> 6);
+ } else if (n_remainder == 7) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ out[i * 8 + 5] = ((in[i * 7 + 4] << 2) & 0x7F);
+ out[i * 8 + 5] |= (in[i * 7 + 5] >> 6);
+ out[i * 8 + 6] = ((in[i * 7 + 5] << 1) & 0x7F);
+ out[i * 8 + 6] |= (in[i * 7 + 6] >> 7);
+ }
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_unpack_fz()
+ *
+ * FZ_ELEM *out : Zz output, unpacked
+ * const uint8_t *in : Zz Vec input, packed in bytes
+ * size_t outlen : Length of out
+ *
+ * This function unpacks an vector of el. in Zz of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_unpack_fz(FZ_ELEM *out, const uint8_t *in,
+ size_t outlen) {
+
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen / 8; i++) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ out[i * 8 + 5] = ((in[i * 3 + 1] << 2) & 0x7);
+ out[i * 8 + 5] |= ((in[i * 3 + 2] >> 6) & 0x7);
+ out[i * 8 + 6] = ((in[i * 3 + 2] >> 3) & 0x7);
+ out[i * 8 + 7] = ((in[i * 3 + 2]) & 0x7);
+ }
+ const uint8_t n_remainder = outlen % 8;
+ if (n_remainder == 1) {
+ out[i * 8] = (in[i * 3] >> 5);
+ }
+ if (n_remainder == 2) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ }
+ if (n_remainder == 3) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ }
+ if (n_remainder == 4) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ }
+ if (n_remainder == 5) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ }
+ if (n_remainder == 6) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ out[i * 8 + 5] = ((in[i * 3 + 1] << 2) & 0x7);
+ out[i * 8 + 5] |= ((in[i * 3 + 2] >> 6) & 0x7);
+ }
+ if (n_remainder == 7) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ out[i * 8 + 5] = ((in[i * 3 + 1] << 2) & 0x7);
+ out[i * 8 + 5] |= ((in[i * 3 + 2] >> 6) & 0x7);
+ out[i * 8 + 6] = ((in[i * 3 + 2] >> 3) & 0x7);
+ }
+
+}
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_uint16_t_pack(uint8_t *out, const uint16_t *in,
+ size_t outlen, size_t inlen, uint8_t btr) {
+ size_t i;
+ size_t in_i = 0;
+ uint8_t left, right;
+ uint8_t skip = 0;
+ if (btr <= 8) {
+ left = 8 - btr;
+ right = 0;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen; i++) {
+ while (right < 8 && in_i < inlen) {
+ out[i] |= (in[in_i] << (left)) >> right;
+ right += 8 - left;
+ left = 8 - btr;
+ in_i++;
+ }
+ if (right != 8) {
+ in_i--;
+ left = 2 * 8 - right;
+ } else {
+ left = 8 - btr;
+ }
+ right = 0;
+ }
+ } else if (btr == 8) {
+ for (i = 0; i < outlen; i++) {
+ out[i] = in[i];
+ }
+ } else if ((btr > 8) && (btr <= 16)) {
+ left = 0;
+ right = btr - 8;
+ skip = 0;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen; i++) {
+ skip = 0;
+ while (skip == 0 && in_i < inlen) {
+ out[i] |= (uint8_t)((in[in_i] << left) >> right);
+ // First case: left == 0,
+ // i.e.: the current value covers the LSBs of the packed value
+ if (left == 0) {
+ skip = 1;
+ //Case 0: This value was complete,
+ //i.e. a new one needs to be started
+ if (right == 0) {
+ in_i++;
+ left = 0;
+ right = btr - 8;
+ }
+ //Case 1: These were not the LSBs of this value,
+ //i.e. its LSBs need to be stored in the next block
+ else if (right <= 8) {
+ left = 8 - right;
+ right = 0;
+ } else {
+ right -= 8;
+ }
+
+ }
+ // Second case: right == 0 and left > 0,
+ // i.e.: the current value is complete its LSBs
+ // are stored in the upper bits
+ else if (right == 0 && left > 0) {
+
+ right = btr - left;
+ left = 0;
+ in_i++;
+
+ }
+ }
+ }
+ }
+ /* PQClean-edit: unused parameter */
+ (void)skip;
+}
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_uint16_t_unpack(uint16_t *out, const uint8_t *in,
+ size_t outlen, size_t inlen, uint8_t btr) {
+ size_t i;
+ uint8_t skip = 0;
+ uint8_t right, left;
+ size_t out_i;
+ if (btr <= 8) {
+ out_i = 0;
+ right = 8 - btr;
+ left = 0;
+ uint8_t mask = (1 << (btr)) - 1;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen; i++) {
+ skip = 0;
+ while (skip == 0 && out_i < outlen) {
+ out[out_i] |= (((in[i] >> (right)) << left) & mask);
+ //Case 1: right > 0, i.e. the current word is done
+ //and there is a new one waiting in the same input
+ if (right > 0) {
+ out_i++;
+ if (right >= btr) {
+ right -= btr;
+ } else {
+ left = btr - right;
+ right = 0;
+ }
+ }
+ //Case 2: right == 0 and left > BITS_TO_REPRESENT(Q-1),
+ //i.e. the current word continues in the next input
+ else if (right == 0) {
+ skip = 1;
+ right = 8 - left;
+ left = 0;
+ if (right == 0) {
+ right = 8 - btr;
+ }
+ }
+ }
+ }
+ } else if (btr == 8) {
+ for (i = 0; i < outlen; i++) {
+ out[i] = in[i];
+ }
+ } else if ((btr > 8) && (btr <= 16)) {
+ left = btr - 8;
+ right = 0;
+ out_i = 0;
+ skip = 0;
+ uint16_t mask = (1 << (btr)) - 1;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen; i++) {
+ skip = 0;
+ while (skip == 0 && out_i < outlen) {
+ // Shift some value of packed poly to correct position
+ // and OR it to the target value
+ out[out_i] |= ((((uint16_t)in[i] << left) >> right) & mask);
+ // First case: the value was incomplete,
+ // i.e. the LSBs are in the next block
+ // This means that left > 0 and right == 0.
+ if (left > 0 && right == 0) {
+ // Right shift of next element for remaining bits
+ if (left <= 8) {
+ right = 8 - left;
+ left = 0;
+ } else {
+ right = 0;
+ left -= 8;
+ }
+ skip = 1;
+ }
+ // Second case: the value was complete, i.e. the LSBs are now stored
+ else if (left == 0) {
+ if (right == 0) {
+ skip = 1;
+ left = btr - 8;
+ } else {
+ left = btr - right;
+ }
+ right = 0;
+ out_i++;
+ }
+ if (left == (btr)) {
+ left = 1;
+ }
+ }
+ }
+ }
+ /* PQClean-edit: unused parameter */
+ (void)skip;
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/pack_unpack.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/pack_unpack.h
new file mode 100644
index 000000000..24c46f00a
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/pack_unpack.h
@@ -0,0 +1,70 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ * @author Jonas Schupp
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include
+#include
+
+#include "parameters.h"
+
+/* compact Z_z/F_q vector encoding functions */
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_vec(uint8_t out[DENSELY_PACKED_FQ_VEC_SIZE],
+ const FQ_ELEM in[N]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fq_syn(uint8_t out[DENSELY_PACKED_FQ_SYN_SIZE],
+ const FQ_ELEM in[N - K]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pack_fz_vec(uint8_t out[DENSELY_PACKED_FZ_VEC_SIZE],
+ const FZ_ELEM in[N]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_pack_fq(uint8_t *out, const FQ_ELEM *in,
+ size_t outlen, size_t inlen);
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_pack_fz(uint8_t *out, const FZ_ELEM *in,
+ size_t outlen, size_t inlen);
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fq_vec(FQ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FQ_VEC_SIZE]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fq_syn(FQ_ELEM out[N - K],
+ const uint8_t in[DENSELY_PACKED_FQ_SYN_SIZE]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_unpack_fz_vec(FZ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE]);
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_unpack_fq(FQ_ELEM *out, const uint8_t *in,
+ size_t outlen, size_t inlen);
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_unpack_fz(FZ_ELEM *out, const uint8_t *in,
+ size_t outlen);
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_uint16_t_unpack(uint16_t *out, const uint8_t *in,
+ size_t outlen, size_t inlen, uint8_t btr);
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generic_uint16_t_pack(uint8_t *out, const uint16_t *in,
+ size_t outlen, size_t inlen, uint8_t btr);
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/parameters.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/parameters.h
new file mode 100644
index 000000000..6c9dc09f6
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/parameters.h
@@ -0,0 +1,131 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+#include
+
+#include "set.h"
+
+/******************************************************************************/
+/*************************** Base Fields Parameters ***************************/
+/******************************************************************************/
+
+/* The same base field and restriction are employed for all categories of RSDP */
+#define Q (127)
+#define Z ( 7)
+/* single-register table representation of E, the value of g^7=1 is also
+ * represented to avoid exponent renormalization*/
+#define RESTR_G_TABLE ((uint64_t) (0x0140201008040201))
+#define RESTR_G_GEN 2
+#define FQ_ELEM uint8_t
+#define FZ_ELEM uint8_t
+#define FQ_DOUBLEPREC uint16_t
+#define FQ_TRIPLEPREC uint32_t
+
+/******************************************************************************/
+/****************************** RSDP Parameters *******************************/
+/******************************************************************************/
+/********************************* Category 1 *********************************/
+#define SEC_MARGIN_LAMBDA (128)
+#define N (127)
+#define K ( 76)
+
+#define T (252)
+#define W (212)
+#define POSITION_IN_FW_STRING_T uint16_t
+
+/********************************* Category 3 *********************************/
+
+/******************************************************************************/
+/****************************** RSDP(G) Parameters ****************************/
+/******************************************************************************/
+
+#define HASH_CSPRNG_DOMAIN_SEP_CONST ((uint16_t)32768)
+
+/************* Helper macros for derived parameter computation ***************/
+
+#define ROUND_UP(amount, round_amt) ( (((amount)+(round_amt)-1)/(round_amt))*(round_amt) )
+
+#define IS_REPRESENTABLE_IN_D_BITS(D, N) \
+(((uint32_t) (N)>=(1UL << ((D)-1)) && (uint32_t) (N)<(1UL << (D))) ? (D) : -1)
+
+#define BITS_TO_REPRESENT(N) \
+ ((N) == 0 ? 1 : (15 \
+ + IS_REPRESENTABLE_IN_D_BITS( 1, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 2, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 3, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 4, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 5, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 6, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 7, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 8, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 9, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(10, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(11, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(12, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(13, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(14, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(15, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(16, N) \
+ ) \
+ )
+
+#define LOG2(L) ( (BITS_TO_REPRESENT(L) > BITS_TO_REPRESENT((L)-1)) ? (BITS_TO_REPRESENT((L)-1)) : (BITS_TO_REPRESENT(L)) )
+
+/***************** Derived parameters *****************************************/
+#define SEED_LENGTH_BYTES (SEC_MARGIN_LAMBDA/8)
+#define KEYPAIR_SEED_LENGTH_BYTES (2*(SEC_MARGIN_LAMBDA/8))
+#define HASH_DIGEST_LENGTH (2*(SEC_MARGIN_LAMBDA/8))
+#define SALT_LENGTH_BYTES (2*(SEC_MARGIN_LAMBDA/8))
+
+#define NUM_LEAVES_MERKLE_TREE (T)
+#define NUM_NODES_MERKLE_TREE (2*NUM_LEAVES_MERKLE_TREE-1)
+
+/*to be derived via script for each T/W*/
+#define NUM_LEAVES_SEED_TREE ( T )
+// #define NUM_NODES_SEED_TREE ( 2*NUM_LEAVES_SEED_TREE-1 )
+#define NUM_INNER_NODES_SEED_TREE ( NUM_NODES_SEED_TREE-NUM_LEAVES_SEED_TREE )
+
+/* Sizes of bitpacked field element vectors
+ * Bitpacking an n-elements vector of num_bits_for_q-1 bits long values
+ * will pack 8 values in num_bits_for_q-1 bytes exactly, leaving the remaining
+ * N % 8 as a tail */
+#define DENSELY_PACKED_FQ_VEC_SIZE ((N/8)*BITS_TO_REPRESENT(Q-1) + \
+ ROUND_UP( ((N%8)*BITS_TO_REPRESENT(Q-1)),8)/8)
+#define DENSELY_PACKED_FQ_SYN_SIZE (((N-K)/8)*BITS_TO_REPRESENT(Q-1) + \
+ ROUND_UP( (((N-K)%8)*BITS_TO_REPRESENT(Q-1)),8)/8)
+#define DENSELY_PACKED_FZ_VEC_SIZE ((N/8)*BITS_TO_REPRESENT(Z-1) + \
+ ROUND_UP( ((N%8)*BITS_TO_REPRESENT(Z-1)),8)/8)
+
+/* Derived parameters computed via compute_derived_parameters.py */
+#define TREE_NODES_TO_STORE 107
+#define NUM_NODES_SEED_TREE 504
+#define NODES_PER_LEVEL_ARRAY {1, 2, 4, 8, 16, 32, 63, 126, 252}
+#define MISSING_NODES_BEFORE_LEVEL_ARRAY {0, 0, 0, 0, 0, 0, 0, 1, 3}
+#define BITS_N_ZQ_CT_RNG 923
+#define BITS_BETA_ZQSTAR_CT_RNG 1817
+#define BITS_V_CT_RNG 27260
+#define BITS_N_ZZ_CT_RNG 493
+#define BITS_CWSTR_RNG 2102
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/restr_arith.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/restr_arith.h
new file mode 100644
index 000000000..a0824b738
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/restr_arith.h
@@ -0,0 +1,77 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "parameters.h"
+
+#define FZRED_SINGLE(x) (((x) & 0x07) + ((x) >> 3))
+#define FZRED_OPPOSITE(x) ((x) ^ 0x07)
+#define FZ_DOUBLE_ZERO_NORM(x) (((x) + (((x) + 1) >> 3)) & 0x07)
+
+static inline
+void fz_dz_norm_sigma(FZ_ELEM v[N]) {
+ for (int i = 0; i < N; i++) {
+ v[i] = FZ_DOUBLE_ZERO_NORM(v[i]);
+ }
+}
+
+/* Elements of the restricted subgroups are represented as the exponents of
+ * the generator */
+static inline
+void restr_vec_sub(FZ_ELEM res[N],
+ const FZ_ELEM a[N],
+ const FZ_ELEM b[N]) {
+ for (int i = 0; i < N; i++) {
+ res[i] = FZRED_SINGLE( a[i] + FZRED_OPPOSITE(b[i]) );
+ }
+}
+
+/* Given the choice of q and z, all elements of G are represented as n-elements
+ * vectors having powers-of-two in {1,2,...,64}.
+ * Employ a round of K&R-HW.
+ * Vectorized comb based HW is also employable, testing a word against
+ * 0x01...01
+ * note that 0x80 is not excluded as sigmas are in double-zero redundant repr.
+ */
+static inline
+int is_fq_vec_in_restr_group(const FQ_ELEM in[N]) {
+ int is_in_ok = 1;
+ for (int i = 0; i < N; i++) {
+ FQ_ELEM tmp;
+ tmp = ( in[i] - (FQ_ELEM)1 ) & in[i];
+ is_in_ok = is_in_ok && (tmp == 0);
+ }
+ return is_in_ok;
+}
+
+static inline
+int is_zz_vec_in_restr_group(const FZ_ELEM in[N]) {
+ int is_in_ok = 1;
+ for (int i = 0; i < N; i++) {
+ is_in_ok = is_in_ok && (in[i] < Z);
+ }
+ return is_in_ok;
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/seedtree.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/seedtree.c
new file mode 100644
index 000000000..0505c9e97
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/seedtree.c
@@ -0,0 +1,273 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include "seedtree.h"
+#include
+#include // memcpy(...), memset(...)
+
+#define LEFT_CHILD(i) (2*(i)+1)
+#define RIGHT_CHILD(i) (2*(i)+2)
+#define PARENT(i) (((i)-1)/2)
+
+/* Seed tree implementation. The binary seed tree is linearized into an array
+ * from root to leaves, and from left to right. The nodes are numbered picking
+ * the indexes from the corresponding full tree, having 2**LOG2(T) leaves */
+#define DIV_BY_TWO_CEIL(i) ((i)/2 + (i) % 2)
+
+#define TO_PUBLISH 1
+#define NOT_TO_PUBLISH 0
+
+/* PQClean-edit: avoid VLA */
+#define CSPRNG_INPUT_LEN (SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + SIZEOF_UINT16)
+//const uint32_t csprng_input_len = SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + sizeof(uint16_t);
+
+/*****************************************************************************/
+/**
+ * const unsigned char *indices: input parameter denoting an array
+ * with a number of binary cells equal to "leaves" representing
+ * the labels of the nodes identified as leaves of the tree[...]
+ * passed as second parameter.
+ * A label = 1 means that the byteseed of the node having the same index
+ * has to be released; = 0, otherwise.
+ *
+ * unsigned char *tree: input/output parameter denoting an array
+ * with a number of binary cells equal to "2*leaves-1";
+ * the first "leaves" cells (i.e., the ones with positions from 0 to leaves-1)
+ * are the ones that will be modified by the current subroutine,
+ * the last "leaves" cells will be a copy of the input array passed as first
+ * parameter.
+ *
+ * uint64_t leaves: input parameter;
+ *
+ */
+
+#define NUM_LEAVES_STENCIL_SEED_TREE ( 1UL << LOG2(T) )
+#define NUM_INNER_NODES_STENCIL_SEED_TREE ( NUM_LEAVES_STENCIL_SEED_TREE-1 )
+#define NUM_NODES_STENCIL_SEED_TREE ( 2*NUM_LEAVES_STENCIL_SEED_TREE-1 )
+
+static void compute_seeds_to_publish(
+ /* linearized binary tree of boolean nodes containing
+ * flags for each node 1-filled nodes are not to be
+ * released */
+ unsigned char flags_tree_to_publish[NUM_NODES_STENCIL_SEED_TREE],
+ /* Boolean Array indicating which of the T seeds must be
+ * released convention as per the above defines */
+ const unsigned char indices_to_publish[T]) {
+ /* the indices to publish may be less than the full leaves, copy them
+ * into the linearized tree leaves */
+ memcpy(flags_tree_to_publish + NUM_INNER_NODES_STENCIL_SEED_TREE,
+ indices_to_publish,
+ T);
+ memset(flags_tree_to_publish,
+ NOT_TO_PUBLISH,
+ NUM_INNER_NODES_STENCIL_SEED_TREE * sizeof(unsigned char));
+ /* compute the value for the internal nodes of the tree starting from the
+ * fathers of the leaves, right to left */
+ for (int i = NUM_LEAVES_STENCIL_SEED_TREE - 2; i >= 0; i--) {
+ if ( ( flags_tree_to_publish[LEFT_CHILD(i)] == TO_PUBLISH) &&
+ ( flags_tree_to_publish[RIGHT_CHILD(i)] == TO_PUBLISH) ) {
+ flags_tree_to_publish[i] = TO_PUBLISH;
+ }
+ }
+} /* end compute_seeds_to_publish */
+
+/**
+ * unsigned char *seed_tree:
+ * it is intended as an output parameter;
+ * storing the linearized binary seed tree
+ *
+ * The root seed is taken as a parameter.
+ * The seed of its TWO children are computed expanding (i.e., shake128...) the
+ * entropy in "salt" + "seedBytes of the parent" +
+ * "int, encoded over 16 bits - uint16_t, associated to each node
+ * from roots to leaves layer-by-layer from left to right,
+ * counting from 0 (the integer bound with the root node)"
+ */
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generate_seed_tree_from_root(unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ const unsigned char root_seed[SEED_LENGTH_BYTES],
+ const unsigned char salt[SALT_LENGTH_BYTES]) {
+ /* input buffer to the CSPRNG, contains a salt, the seed to be expanded
+ * and the integer index of the node being expanded for domain separation */
+ const uint32_t csprng_input_len = SALT_LENGTH_BYTES +
+ SEED_LENGTH_BYTES +
+ sizeof(uint16_t);
+ unsigned char csprng_input[CSPRNG_INPUT_LEN];
+ CSPRNG_STATE_T tree_csprng_state;
+ memcpy(csprng_input + SEED_LENGTH_BYTES, salt, SALT_LENGTH_BYTES);
+
+ /* Set the root seed in the tree from the received parameter */
+ memcpy(seed_tree, root_seed, SEED_LENGTH_BYTES);
+
+ /* missing_nodes_before[i] contains the total number of missing nodes before
+ * level i (the root is level 0). This constant vector is precomputed */
+ const int missing_nodes_before[LOG2(T) + 1] = MISSING_NODES_BEFORE_LEVEL_ARRAY;
+ /* Generate the log_2(t) layers from the root, each iteration generates a tree
+ * level; iterate on nodes of the parent level */
+ const int nodes_in_level[LOG2(T) + 1] = NODES_PER_LEVEL_ARRAY;
+ int ancestors = 0;
+ for (int level = 0; level < LOG2(T); level++) {
+ for (int node_in_level = 0; node_in_level < nodes_in_level[level]; node_in_level++ ) {
+ uint16_t father_node_idx = ancestors + node_in_level;
+ uint16_t father_node_storage_idx = father_node_idx - missing_nodes_before[level];
+ /* prepare the CSPRNG input to expand the children of node i */
+ memcpy(csprng_input,
+ seed_tree + father_node_storage_idx * SEED_LENGTH_BYTES,
+ SEED_LENGTH_BYTES);
+ *((uint16_t *)(csprng_input + SALT_LENGTH_BYTES + SEED_LENGTH_BYTES)) = father_node_idx;
+ /* expand the children (stored contiguously) */
+ initialize_csprng(&tree_csprng_state, csprng_input, csprng_input_len);
+ csprng_randombytes(seed_tree + (LEFT_CHILD(father_node_idx) - missing_nodes_before[level + 1] ) *SEED_LENGTH_BYTES,
+ SEED_LENGTH_BYTES,
+ &tree_csprng_state);
+ if ((RIGHT_CHILD(father_node_idx) - missing_nodes_before[level + 1]) < NUM_NODES_SEED_TREE ) {
+ csprng_randombytes(seed_tree + (RIGHT_CHILD(father_node_idx) - missing_nodes_before[level + 1])*SEED_LENGTH_BYTES,
+ SEED_LENGTH_BYTES,
+ &tree_csprng_state);
+ }
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&tree_csprng_state);
+
+ }
+ ancestors += (1L << level);
+ }
+} /* end generate_seed_tree */
+
+/*****************************************************************************/
+
+/*****************************************************************************/
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_publish_seeds(unsigned char *seed_storage,
+ // OUTPUT: sequence of seeds to be released
+ const unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ // INPUT: binary array storing in each cell a binary value (i.e., 0 or 1),
+ // which in turn denotes if the seed of the node with the same index
+ // must be released (i.e., cell == 0) or not (i.e., cell == 1).
+ // Indeed the seed will be stored in the sequence computed as a result into the out[...] array.
+ // INPUT: binary array denoting which node has to be released (cell == TO_PUBLISH) or not
+ const unsigned char indices_to_publish[T]
+ ) {
+ /* complete linearized binary tree containing boolean values determining
+ * if a node is to be released or not. Nodes set to 1 are not to be released
+ * oldest ancestor of sets of nodes equal to 0 are to be released */
+ unsigned char flags_tree_to_publish[NUM_NODES_STENCIL_SEED_TREE] = {0};
+ compute_seeds_to_publish(flags_tree_to_publish, indices_to_publish);
+ const int missing_nodes_before[LOG2(T) + 1] = MISSING_NODES_BEFORE_LEVEL_ARRAY;
+ const int nodes_in_level[LOG2(T) + 1] = NODES_PER_LEVEL_ARRAY;
+
+ int num_seeds_published = 0;
+ int node_idx = 1;
+ /* no sense in trying to publish the root node, start examining from level 1
+ * */
+
+ int ancestors = 1;
+ for (int level = 1; level < LOG2(T) + 1; level++) {
+ for (int node_in_level = 0; node_in_level < nodes_in_level[level]; node_in_level++ ) {
+ node_idx = ancestors + node_in_level;
+ int node_storage_idx = node_idx - missing_nodes_before[level];
+ if ( (flags_tree_to_publish[node_idx] == TO_PUBLISH) &&
+ (flags_tree_to_publish[PARENT(node_idx)] == NOT_TO_PUBLISH) ) {
+ memcpy(seed_storage + num_seeds_published * SEED_LENGTH_BYTES,
+ seed_tree + node_storage_idx * SEED_LENGTH_BYTES,
+ SEED_LENGTH_BYTES);
+ num_seeds_published++;
+ }
+ }
+ ancestors += (1L << level);
+ }
+
+ return num_seeds_published;
+} /* end PQCLEAN_CROSSRSDP128BALANCED_CLEAN_publish_seeds */
+
+/*****************************************************************************/
+
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_regenerate_round_seeds(unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ const unsigned char indices_to_publish[T],
+ const unsigned char *stored_seeds,
+ const unsigned char salt[SALT_LENGTH_BYTES]) {
+ /* complete linearized binary tree containing boolean values determining
+ * if a node is to be released or not. Nodes set to 1 are not to be released
+ * oldest ancestor of sets of nodes equal to 0 are to be released */
+ unsigned char flags_tree_to_publish[NUM_NODES_STENCIL_SEED_TREE] = {0};
+ compute_seeds_to_publish(flags_tree_to_publish, indices_to_publish);
+
+ const uint32_t csprng_input_len = SALT_LENGTH_BYTES +
+ SEED_LENGTH_BYTES +
+ sizeof(uint16_t);
+ unsigned char csprng_input[CSPRNG_INPUT_LEN];
+ CSPRNG_STATE_T tree_csprng_state;
+
+ memcpy(csprng_input + SEED_LENGTH_BYTES, salt, SALT_LENGTH_BYTES);
+
+ int nodes_used = 0;
+ /* missing_nodes_before[i] contains the total number of missing nodes before
+ * level i. Level 0 is taken to be the tree root This constant vector is precomputed */
+ const int missing_nodes_before[LOG2(T) + 1] = MISSING_NODES_BEFORE_LEVEL_ARRAY;
+
+ /* regenerating the seed tree never starts from the root, as it is never
+ * disclosed */
+ int ancestors = 0;
+ const int nodes_in_level[LOG2(T) + 1] = NODES_PER_LEVEL_ARRAY;
+ for (int level = 0; level <= LOG2(T); level++) {
+ for (int node_in_level = 0; node_in_level < nodes_in_level[level]; node_in_level++ ) {
+ uint16_t father_node_idx = ancestors + node_in_level;
+ uint16_t father_node_storage_idx = father_node_idx - missing_nodes_before[level];
+ /* if the current node is a seed which was published, memcpy it in place */
+ if ( flags_tree_to_publish[father_node_idx] == TO_PUBLISH ) {
+ if ( flags_tree_to_publish[PARENT(father_node_idx)] == NOT_TO_PUBLISH ) {
+ memcpy(seed_tree + SEED_LENGTH_BYTES * (father_node_storage_idx),
+ stored_seeds + SEED_LENGTH_BYTES * nodes_used,
+ SEED_LENGTH_BYTES );
+ nodes_used++;
+ }
+ }
+ /* if the current node is published and not a leaf,
+ * CSPRNG-expand its children */
+ if ( ( flags_tree_to_publish[father_node_idx] == TO_PUBLISH ) &&
+ ( level < LOG2(T)) ) {
+ /* prepare the CSPRNG input to expand the children of node father_node_idx */
+ memcpy(csprng_input,
+ seed_tree + (father_node_storage_idx)*SEED_LENGTH_BYTES,
+ SEED_LENGTH_BYTES);
+ *((uint16_t *)(csprng_input + SALT_LENGTH_BYTES + SEED_LENGTH_BYTES)) = father_node_idx;
+ /* expand the children (stored contiguously) */
+ initialize_csprng(&tree_csprng_state, csprng_input, csprng_input_len);
+ csprng_randombytes(seed_tree + (LEFT_CHILD(father_node_idx) - missing_nodes_before[level + 1])*SEED_LENGTH_BYTES,
+ SEED_LENGTH_BYTES,
+ &tree_csprng_state);
+ csprng_randombytes(seed_tree + (RIGHT_CHILD(father_node_idx) - missing_nodes_before[level + 1])*SEED_LENGTH_BYTES,
+ SEED_LENGTH_BYTES,
+ &tree_csprng_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&tree_csprng_state);
+ }
+ }
+ ancestors += (1L << level);
+ }
+ return nodes_used;
+} /* end regenerate_leaves */
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/seedtree.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/seedtree.h
new file mode 100644
index 000000000..23176bb01
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/seedtree.h
@@ -0,0 +1,54 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "csprng_hash.h"
+#include "parameters.h"
+
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_pseed(unsigned char seed[SEED_LENGTH_BYTES]);
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_ptree(unsigned char seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES]);
+
+/******************************************************************************/
+void PQCLEAN_CROSSRSDP128BALANCED_CLEAN_generate_seed_tree_from_root(unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ const unsigned char root_seed[SEED_LENGTH_BYTES],
+ const unsigned char salt[SALT_LENGTH_BYTES]) ;
+
+/******************************************************************************/
+/* returns the number of seeds which have been published */
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_publish_seeds(unsigned char *seed_storage,
+ const unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ // binary array denoting if node has to be released (cell == 0) or not
+ const unsigned char indices_to_publish[T]);
+
+/******************************************************************************/
+/* returns the number of seeds which have been used to regenerate the tree */
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_regenerate_round_seeds(unsigned char
+ seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES],
+ const unsigned char indices_to_publish[T],
+ const unsigned char *stored_seeds,
+ const unsigned char salt[SALT_LENGTH_BYTES]); // input
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/set.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/set.h
new file mode 100644
index 000000000..4db25c391
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/set.h
@@ -0,0 +1,23 @@
+
+#define RSDP 1
+#define CATEGORY_1 1
+#define BALANCED 1
+
+#undef NO_TREES
+
+/* liboqs-edit: when compiling avx2 just assume that Intel Instrinsics are available */
+#define IMPLEMENTATION_clean
+
+/* PQClean-edit: avoid VLA (don't call sizeof() when creating arrays) */
+#define SIZEOF_UINT16 2
+
+/* Undefine unused macros to facilitate dead code removal using unifdef */
+#undef SHA_3_LIBKECCAK
+/* Variant */
+#undef RSDPG
+/* Category */
+#undef CATEGORY_3
+#undef CATEGORY_5
+/* Target */
+#undef SPEED
+#undef SIG_SIZE
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/sha3.h b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/sha3.h
new file mode 100644
index 000000000..5045aaeeb
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/sha3.h
@@ -0,0 +1,146 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "fips202.h"
+/* standalone FIPS-202 implementation has
+ * different states for SHAKE depending on security level*/
+#define SHAKE_STATE_STRUCT shake128incctx
+// %%%%%%%%%%%%%%%%%% Self-contained SHAKE x1 Wrappers %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+static inline
+void xof_shake_init(SHAKE_STATE_STRUCT *state, int val) {
+ /* PQClean-edit: unused parameter */
+ (void)val;
+ shake128_inc_init(state);
+}
+
+static inline
+void xof_shake_update(SHAKE_STATE_STRUCT *state,
+ const unsigned char *input,
+ uint32_t inputByteLen) {
+ shake128_inc_absorb(state,
+ (const uint8_t *)input,
+ inputByteLen);
+}
+
+static inline
+void xof_shake_final(SHAKE_STATE_STRUCT *state) {
+ shake128_inc_finalize(state);
+}
+
+static inline
+void xof_shake_extract(SHAKE_STATE_STRUCT *state,
+ unsigned char *output,
+ uint32_t outputByteLen) {
+ shake128_inc_squeeze(output, outputByteLen, state);
+}
+
+/* PQClean-edit: CSPRNG release context */
+static inline
+void xof_shake_release(SHAKE_STATE_STRUCT *state) {
+ shake128_inc_ctx_release(state);
+}
+
+// %%%%%%%%%%%%%%%%%% Self-contained SHAKE x4 Wrappers %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#include "fips202x4.h"
+#define SHAKE_X4_STATE_STRUCT shake128x4incctx
+#define SHAKE_X4_INIT shake128x4_inc_init
+#define SHAKE_X4_ABSORB shake128x4_inc_absorb
+#define SHAKE_X4_FINALIZE shake128x4_inc_finalize
+#define SHAKE_X4_SQUEEZE shake128x4_inc_squeeze
+#define SHAKE_X4_RELEASE shake128x4_inc_ctx_release
+
+static inline void xof_shake_x4_init(SHAKE_X4_STATE_STRUCT *states) {
+ SHAKE_X4_INIT(states);
+}
+static inline void xof_shake_x4_update(SHAKE_X4_STATE_STRUCT *states,
+ const unsigned char *in1,
+ const unsigned char *in2,
+ const unsigned char *in3,
+ const unsigned char *in4,
+ uint32_t singleInputByteLen) {
+ SHAKE_X4_ABSORB(states, in1, in2, in3, in4, singleInputByteLen);
+}
+static inline void xof_shake_x4_final(SHAKE_X4_STATE_STRUCT *states) {
+ SHAKE_X4_FINALIZE(states);
+}
+static inline void xof_shake_x4_extract(SHAKE_X4_STATE_STRUCT *states,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3,
+ unsigned char *out4,
+ uint32_t singleOutputByteLen) {
+ SHAKE_X4_SQUEEZE(out1, out2, out3, out4, singleOutputByteLen, states);
+}
+static inline void xof_shake_x4_release(SHAKE_X4_STATE_STRUCT *states) {
+ SHAKE_X4_RELEASE(states);
+}
+
+// %%%%%%%%%%%%%%%%%% Self-contained SHAKE x2 Wrappers %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+/* SHAKE_x2 just calls SHAKE_x1 twice. If a suitable SHAKE_x2 implementation becomes available, it should be used instead */
+
+typedef struct {
+ SHAKE_STATE_STRUCT state1;
+ SHAKE_STATE_STRUCT state2;
+} shake_x2_ctx;
+#define SHAKE_X2_STATE_STRUCT shake_x2_ctx
+static inline void xof_shake_x2_init(SHAKE_X2_STATE_STRUCT *states) {
+ xof_shake_init(&(states->state1), 0);
+ xof_shake_init(&(states->state2), 0);
+}
+static inline void xof_shake_x2_update(SHAKE_X2_STATE_STRUCT *states,
+ const unsigned char *in1,
+ const unsigned char *in2,
+ uint32_t singleInputByteLen) {
+ xof_shake_update(&(states->state1), (const uint8_t *)in1, singleInputByteLen);
+ xof_shake_update(&(states->state2), (const uint8_t *)in2, singleInputByteLen);
+}
+static inline void xof_shake_x2_final(SHAKE_X2_STATE_STRUCT *states) {
+ xof_shake_final(&(states->state1));
+ xof_shake_final(&(states->state2));
+}
+static inline void xof_shake_x2_extract(SHAKE_X2_STATE_STRUCT *states,
+ unsigned char *out1,
+ unsigned char *out2,
+ uint32_t singleOutputByteLen) {
+ xof_shake_extract(&(states->state1), out1, singleOutputByteLen);
+ xof_shake_extract(&(states->state2), out2, singleOutputByteLen);
+}
+static inline void xof_shake_x2_release(SHAKE_X2_STATE_STRUCT *states) {
+ xof_shake_release(&(states->state1));
+ xof_shake_release(&(states->state2));
+}
+
+// %%%%%%%%%%%%%%%%%%%% Parallel SHAKE State Struct %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+typedef struct {
+ SHAKE_STATE_STRUCT state1;
+ SHAKE_X2_STATE_STRUCT state2;
+ SHAKE_X4_STATE_STRUCT state4;
+} par_shake_ctx;
diff --git a/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/sign.c b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/sign.c
new file mode 100644
index 000000000..4fefee044
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-balanced_clean/sign.c
@@ -0,0 +1,122 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include "api.h"
+#include "CROSS.h"
+#include "parameters.h"
+#include // size_t
+#include // memcpy
+/*----------------------------------------------------------------------------*/
+
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_keypair(unsigned char *pk,
+ unsigned char *sk) {
+ /* keygen cannot fail */
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CROSS_keygen((prikey_t *) sk,
+ (pubkey_t *) pk);
+
+ return 0; // NIST convention: 0 == zero errors
+} // end PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_keypair
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*... generating a signed message sm[0],sm[1],...,sm[*smlen-1] */
+/*... from original message m[0],m[1],...,m[mlen-1] */
+/*... under secret key sk[0],sk[1],... */
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign(unsigned char *sm,
+ size_t *smlen, // out parameter
+ const unsigned char *m, size_t mlen, // in parameter
+ const unsigned char *sk) { // in parameter
+ /* sign cannot fail */
+ memcpy(sm, m, mlen);
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CROSS_sign((const prikey_t *) sk, // in parameter
+ (const char *const) m, (const size_t) mlen, // in parameter
+ (CROSS_sig_t *) (sm + mlen)); // out parameter
+ *smlen = mlen + (size_t) sizeof(CROSS_sig_t);
+
+ return 0; // NIST convention: 0 == zero errors
+} // end PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*. ... verifying a signed message sm[0],sm[1],...,sm[smlen-1] */
+/*. ... under public key pk[0],pk[1],... */
+/*. ... and producing original message m[0],m[1],...,m[*mlen-1] */
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_open(unsigned char *m,
+ size_t *mlen, // out parameter
+ const unsigned char *sm, size_t smlen, // in parameter
+ const unsigned char *pk) { // in parameter
+
+ /* verify returns 1 if signature is ok, 0 otherwise */
+ *mlen = smlen - (size_t) sizeof(CROSS_sig_t);
+
+ memcpy((unsigned char *) m, (const unsigned char *) sm, (size_t) *mlen);
+ int ok = PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CROSS_verify((const pubkey_t *const)
+ pk, // in parameter
+ (const char *const) m, (const size_t) * mlen, // in parameter
+ (const CROSS_sig_t *const) (sm + *mlen)); // in parameter
+
+ return ok - 1; // NIST convention: 0 == zero errors, -1 == error condition
+} // end PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_open
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*... generating a signature sig[0],sig[1],...,sig[*siglen-1] */
+/*... from original message m[0],m[1],...,m[mlen-1] */
+/*... under secret key sk[0],sk[1],... */
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_signature(unsigned char *sig, size_t *siglen, // out parameter
+ const unsigned char *m, size_t mlen, // in parameter
+ const unsigned char *sk // in parameter
+ ) {
+ /* sign cannot fail */
+ PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CROSS_sign((const prikey_t *) sk, // in parameter
+ (const char *const) m, (const size_t) mlen, // in parameter
+ (CROSS_sig_t *) sig); // out parameter
+ *siglen = (size_t) sizeof(CROSS_sig_t);
+
+ return 0; // NIST convention: 0 == zero errors
+} // end PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_signature
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*. ... verifying a signature sig[0],sig[1],...,sig[siglen-1] */
+/*. ... under public key pk[0],pk[1],... */
+/*. ... and producing original message m[0],m[1],...,m[*mlen-1] */
+int PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_verify(const unsigned char *sig, size_t siglen, // in parameter
+ const unsigned char *m, size_t mlen, // in parameter
+ const unsigned char *pk // in parameter
+ ) {
+
+ /* PQClean-edit: unused parameter */
+ (void)siglen;
+
+ /* verify returns 1 if signature is ok, 0 otherwise */
+ int ok = PQCLEAN_CROSSRSDP128BALANCED_CLEAN_CROSS_verify((const pubkey_t *const) pk, // in parameter
+ (const char *const) m, (const size_t) mlen, // in parameter
+ (const CROSS_sig_t *const) sig); // in parameter
+
+ return ok - 1; // NIST convention: 0 == zero errors, -1 == error condition
+} // end PQCLEAN_CROSSRSDP128BALANCED_CLEAN_crypto_sign_verify
+
+/*----------------------------------------------------------------------------*/
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/CROSS.c b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/CROSS.c
new file mode 100644
index 000000000..3924a8ecd
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/CROSS.c
@@ -0,0 +1,548 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+#include
+#include
+
+#include "architecture_detect.h"
+#include "CROSS.h"
+#include "csprng_hash.h"
+#include "fq_arith.h"
+#include "merkle_tree.h"
+#include "pack_unpack.h"
+#include "randombytes.h"
+#include "seedtree.h"
+
+static
+void expand_public_seed(FQ_ELEM V_tr[K][N - K],
+ const uint8_t seed_pub[KEYPAIR_SEED_LENGTH_BYTES]) {
+ CSPRNG_STATE_T CSPRNG_state_mat;
+ initialize_csprng(&CSPRNG_state_mat, seed_pub, KEYPAIR_SEED_LENGTH_BYTES);
+ CSPRNG_fq_mat(V_tr, &CSPRNG_state_mat);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_mat);
+}
+
+static
+void expand_private_seed(FZ_ELEM eta[N],
+ FQ_ELEM V_tr[K][N - K],
+ const uint8_t seed[KEYPAIR_SEED_LENGTH_BYTES]) {
+ uint8_t seede_seed_pub[2][KEYPAIR_SEED_LENGTH_BYTES];
+ CSPRNG_STATE_T CSPRNG_state;
+ initialize_csprng(&CSPRNG_state, seed, KEYPAIR_SEED_LENGTH_BYTES);
+ csprng_randombytes((uint8_t *)seede_seed_pub,
+ 2 * KEYPAIR_SEED_LENGTH_BYTES,
+ &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ expand_public_seed(V_tr, seede_seed_pub[1]);
+
+ CSPRNG_STATE_T CSPRNG_state_eta;
+ initialize_csprng(&CSPRNG_state_eta, seede_seed_pub[0], KEYPAIR_SEED_LENGTH_BYTES);
+ CSPRNG_zz_vec(eta, &CSPRNG_state_eta);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_eta);
+}
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_CROSS_keygen(prikey_t *SK,
+ pubkey_t *PK) {
+ /* generation of random material for public and private key */
+ randombytes(SK->seed, KEYPAIR_SEED_LENGTH_BYTES);
+ uint8_t seede_seed_pub[2][KEYPAIR_SEED_LENGTH_BYTES];
+
+ CSPRNG_STATE_T CSPRNG_state;
+ initialize_csprng(&CSPRNG_state, SK->seed, KEYPAIR_SEED_LENGTH_BYTES);
+ csprng_randombytes((uint8_t *)seede_seed_pub,
+ 2 * KEYPAIR_SEED_LENGTH_BYTES,
+ &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ memcpy(PK->seed_pub, seede_seed_pub[1], KEYPAIR_SEED_LENGTH_BYTES);
+
+ /* expansion of matrix/matrices */
+ FQ_ELEM V_tr[K][N - K];
+ expand_public_seed(V_tr, PK->seed_pub);
+
+ /* expansion of secret key material */
+ FZ_ELEM eta[N];
+ CSPRNG_STATE_T CSPRNG_state_eta;
+ initialize_csprng(&CSPRNG_state_eta, seede_seed_pub[0], KEYPAIR_SEED_LENGTH_BYTES);
+
+ CSPRNG_zz_vec(eta, &CSPRNG_state_eta);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_eta);
+
+ /* compute public syndrome */
+ FQ_ELEM pub_syn[N - K];
+ restr_vec_by_fq_matrix(pub_syn, eta, V_tr);
+ fq_dz_norm_synd(pub_syn);
+ PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_syn(PK->s, pub_syn);
+}
+
+/* sign cannot fail */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_CROSS_sign(const prikey_t *const SK,
+ const char *const m,
+ const size_t mlen,
+ CROSS_sig_t *const sig) {
+ /* Wipe any residual information in the sig structure allocated by the
+ * caller */
+ memset(sig, 0, sizeof(CROSS_sig_t));
+ /* Key material expansion */
+ FQ_ELEM V_tr[K][N - K];
+ FZ_ELEM eta[N];
+ expand_private_seed(eta, V_tr, SK->seed);
+
+ /* Expanded */
+ alignas(EPI8_PER_REG) uint16_t V_tr_avx[K][ROUND_UP(N - K, EPI16_PER_REG)] = {{0}};
+ for (int i = 0; i < K; i++) {
+ for (int j = 0; j < N - K; j++) {
+ V_tr_avx[i][j] = V_tr[i][j];
+ }
+ }
+
+ uint8_t root_seed[SEED_LENGTH_BYTES];
+ randombytes(root_seed, SEED_LENGTH_BYTES);
+ randombytes(sig->salt, SALT_LENGTH_BYTES);
+
+ unsigned char rounds_seeds[T * SEED_LENGTH_BYTES] = {0};
+ PQCLEAN_CROSSRSDP128FAST_AVX2_compute_round_seeds(rounds_seeds, root_seed, sig->salt);
+
+ FZ_ELEM eta_tilde[T][N];
+ FZ_ELEM sigma[T][N];
+ FQ_ELEM u_tilde[T][N];
+ FQ_ELEM s_tilde[N - K];
+
+ uint8_t cmt_0_i_input[4][DENSELY_PACKED_FQ_SYN_SIZE +
+ DENSELY_PACKED_FZ_VEC_SIZE +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ const int offset_salt = DENSELY_PACKED_FQ_SYN_SIZE + DENSELY_PACKED_FZ_VEC_SIZE;
+ const int offset_round_idx = offset_salt + SALT_LENGTH_BYTES;
+
+ uint8_t cmt_1_i_input[4][SEED_LENGTH_BYTES +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+
+ /* place the salt in the hash input for all parallel instances of keccak */
+ for (int instance = 0; instance < 4; instance++) {
+ /* cmt_0_i_input is syndrome||sigma ||salt ; place salt at the end */
+ memcpy(cmt_0_i_input[instance] + offset_salt, sig->salt, SALT_LENGTH_BYTES);
+ /* cmt_1_i_input is concat(seed,salt,round index) */
+ memcpy(cmt_1_i_input[instance] + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ }
+
+ uint8_t cmt_0[T][HASH_DIGEST_LENGTH] = {0};
+ uint8_t cmt_1[T][HASH_DIGEST_LENGTH] = {0};
+
+ /* enqueue the calls to hash */
+ int to_hash = 0;
+ int round_idx_queue[4] = {0};
+
+ CSPRNG_STATE_T CSPRNG_state;
+ for (uint16_t i = 0; i < T; i++) {
+ to_hash++;
+ round_idx_queue[to_hash - 1] = i;
+ /* CSPRNG is fed with concat(seed,salt,round index) represented
+ * as a 2 bytes little endian unsigned integer */
+ uint8_t csprng_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ memcpy(csprng_input, rounds_seeds + SEED_LENGTH_BYTES * i, SEED_LENGTH_BYTES);
+ memcpy(csprng_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ /* i+c */
+ uint16_t domain_sep_i = i + NUM_NODES_SEED_TREE;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES] = (domain_sep_i >> 8) & 0xFF;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + 1] = domain_sep_i & 0xFF;
+
+ /* expand seed[i] into seed_e and seed_u */
+ initialize_csprng(&CSPRNG_state,
+ csprng_input,
+ SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t));
+ /* expand eta_tilde */
+ CSPRNG_zz_vec(eta_tilde[i], &CSPRNG_state);
+ restr_vec_sub(sigma[i], eta, eta_tilde[i]);
+
+ FQ_ELEM v[N];
+ convert_restr_vec_to_fq(v, sigma[i]);
+ fz_dz_norm_sigma(sigma[i]);
+ /* expand u_tilde */
+ CSPRNG_fq_vec(u_tilde[i], &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ FQ_ELEM u[N];
+ fq_vec_by_fq_vec_pointwise(u, v, u_tilde[i]);
+ fq_vec_by_fq_matrix(s_tilde, u, V_tr_avx);
+ fq_dz_norm_synd(s_tilde);
+
+ /* cmt_0_i_input contains s-tilde || sigma_i || salt */
+ PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_syn(cmt_0_i_input[to_hash - 1], s_tilde);
+
+ PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fz_vec(cmt_0_i_input[to_hash - 1] + DENSELY_PACKED_FQ_SYN_SIZE, sigma[i]);
+ /* i+c+dsc */
+ uint16_t domain_sep_idx_hash = domain_sep_i + HASH_CSPRNG_DOMAIN_SEP_CONST;
+ /* Fixed endianness marshalling of round counter */
+ cmt_0_i_input[to_hash - 1][offset_round_idx] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_0_i_input[to_hash - 1][offset_round_idx + 1] = domain_sep_idx_hash & 0xFF;
+
+ memcpy(cmt_1_i_input[to_hash - 1],
+ rounds_seeds + SEED_LENGTH_BYTES * i,
+ SEED_LENGTH_BYTES);
+
+ cmt_1_i_input[to_hash - 1][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_1_i_input[to_hash - 1][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + 1] = domain_sep_idx_hash & 0xFF;
+
+ if (to_hash == 4 || i == T - 1) {
+ par_hash(
+ to_hash,
+ cmt_0[round_idx_queue[0]],
+ cmt_0[round_idx_queue[1]],
+ cmt_0[round_idx_queue[2]],
+ cmt_0[round_idx_queue[3]],
+ cmt_0_i_input[0],
+ cmt_0_i_input[1],
+ cmt_0_i_input[2],
+ cmt_0_i_input[3],
+ sizeof(cmt_0_i_input) / 4
+ );
+ par_hash(
+ to_hash,
+ cmt_1[round_idx_queue[0]],
+ cmt_1[round_idx_queue[1]],
+ cmt_1[round_idx_queue[2]],
+ cmt_1[round_idx_queue[3]],
+ cmt_1_i_input[0],
+ cmt_1_i_input[1],
+ cmt_1_i_input[2],
+ cmt_1_i_input[3],
+ sizeof(cmt_1_i_input) / 4
+ );
+ to_hash = 0;
+ }
+ }
+
+ /* vector containing d_0 and d_1 from spec */
+ uint8_t commit_digests[2][HASH_DIGEST_LENGTH];
+ PQCLEAN_CROSSRSDP128FAST_AVX2_merkle_tree_root_compute(commit_digests[0], cmt_0);
+ hash(commit_digests[1], (unsigned char *)cmt_1, sizeof(cmt_1));
+ hash(sig->digest_01,
+ (unsigned char *) commit_digests,
+ sizeof(commit_digests));
+
+ /* first challenge extraction */
+ uint8_t beta_buf[2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES];
+ /* place d_m at the beginning of the input of the hash generating d_beta*/
+ hash(beta_buf, (uint8_t *) m, mlen);
+ memcpy(beta_buf + HASH_DIGEST_LENGTH, sig->digest_01, HASH_DIGEST_LENGTH);
+ memcpy(beta_buf + 2 * HASH_DIGEST_LENGTH, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t d_beta[HASH_DIGEST_LENGTH];
+ hash(d_beta, beta_buf, 2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES);
+
+ FQ_ELEM beta[T];
+ initialize_csprng(&CSPRNG_state, d_beta, HASH_DIGEST_LENGTH);
+ CSPRNG_fq_vec_beta(beta, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ /* Computation of the first round of responses */
+ FQ_ELEM y[T][N];
+ for (int i = 0; i < T; i++) {
+ fq_vec_by_restr_vec_scaled(y[i],
+ eta_tilde[i],
+ beta[i],
+ u_tilde[i]);
+ fq_dz_norm(y[i]);
+ }
+ /* y vectors are packed before being hashed */
+ uint8_t digest_b_buf[T * DENSELY_PACKED_FQ_VEC_SIZE + HASH_DIGEST_LENGTH];
+ for (int x = 0; x < T; x++) {
+ PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_vec(digest_b_buf + (x * DENSELY_PACKED_FQ_VEC_SIZE), y[x]);
+ }
+ /* Second challenge extraction */
+ memcpy(digest_b_buf + T * DENSELY_PACKED_FQ_VEC_SIZE, d_beta, HASH_DIGEST_LENGTH);
+
+ hash(sig->digest_b, digest_b_buf, sizeof(digest_b_buf));
+
+ uint8_t fixed_weight_b[T] = {0};
+ PQCLEAN_CROSSRSDP128FAST_AVX2_expand_digest_to_fixed_weight(fixed_weight_b, sig->digest_b);
+
+ /* Computation of the second round of responses */
+
+ PQCLEAN_CROSSRSDP128FAST_AVX2_merkle_tree_proof_compute(sig->mtp, cmt_0, fixed_weight_b);
+ PQCLEAN_CROSSRSDP128FAST_AVX2_publish_round_seeds(sig->stp, rounds_seeds, fixed_weight_b);
+
+ int published_rsps = 0;
+ for (int i = 0; i < T; i++) {
+ if (fixed_weight_b[i] == 0) {
+ /* PQClean-edit: remove assertion */
+ //assert(published_rsps < T-W);
+ PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_vec(sig->rsp_0[published_rsps].y, y[i]);
+ PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fz_vec(sig->rsp_0[published_rsps].sigma, sigma[i]);
+ memcpy(sig->rsp_1[published_rsps], cmt_1[i], HASH_DIGEST_LENGTH);
+ published_rsps++;
+ }
+ }
+}
+
+/* PQClean-edit: avoid VLA */
+#define CSPRNG_INPUT_LENGTH (SALT_LENGTH_BYTES+SEED_LENGTH_BYTES+SIZEOF_UINT16)
+//const int csprng_input_length = SALT_LENGTH_BYTES+SEED_LENGTH_BYTES+sizeof(uint16_t);
+
+/* verify returns 1 if signature is ok, 0 otherwise */
+int PQCLEAN_CROSSRSDP128FAST_AVX2_CROSS_verify(const pubkey_t *const PK,
+ const char *const m,
+ const size_t mlen,
+ const CROSS_sig_t *const sig) {
+ CSPRNG_STATE_T CSPRNG_state;
+
+ FQ_ELEM V_tr[K][N - K];
+ expand_public_seed(V_tr, PK->seed_pub);
+ /* Expanded */
+ alignas(EPI8_PER_REG) uint16_t V_tr_avx[K][ROUND_UP(N - K, EPI16_PER_REG)] = {{0}};
+ for (int i = 0; i < K; i++) {
+ for (int j = 0; j < N - K; j++) {
+ V_tr_avx[i][j] = V_tr[i][j];
+ }
+ }
+
+ FQ_ELEM pub_syn[N - K];
+ PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fq_syn(pub_syn, PK->s);
+
+ uint8_t beta_buf[2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES];
+ hash(beta_buf, (uint8_t *) m, mlen);
+ memcpy(beta_buf + HASH_DIGEST_LENGTH, sig->digest_01, HASH_DIGEST_LENGTH);
+ memcpy(beta_buf + 2 * HASH_DIGEST_LENGTH, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t d_beta[HASH_DIGEST_LENGTH];
+ hash(d_beta, beta_buf, sizeof(beta_buf));
+
+ FQ_ELEM beta[T];
+ initialize_csprng(&CSPRNG_state, d_beta, HASH_DIGEST_LENGTH);
+ CSPRNG_fq_vec_beta(beta, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ uint8_t fixed_weight_b[T] = {0};
+ PQCLEAN_CROSSRSDP128FAST_AVX2_expand_digest_to_fixed_weight(fixed_weight_b, sig->digest_b);
+
+ uint8_t rounds_seeds[T * SEED_LENGTH_BYTES] = {0};
+ PQCLEAN_CROSSRSDP128FAST_AVX2_regenerate_round_seeds(rounds_seeds, fixed_weight_b, sig->stp);
+
+ uint8_t cmt_0_i_input[4][DENSELY_PACKED_FQ_SYN_SIZE +
+ DENSELY_PACKED_FZ_VEC_SIZE +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ const int offset_salt = DENSELY_PACKED_FQ_SYN_SIZE + DENSELY_PACKED_FZ_VEC_SIZE;
+ const int offset_round_idx = offset_salt + SALT_LENGTH_BYTES;
+
+ uint8_t cmt_1_i_input[4][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t)];
+
+ /* place the salt in the hash input for all parallel instances of keccak */
+ for (int instance = 0; instance < 4; instance++) {
+ /* cmt_0_i_input is syndrome||sigma ||salt */
+ memcpy(cmt_0_i_input[instance] + offset_salt, sig->salt, SALT_LENGTH_BYTES);
+ /* cmt_1_i_input is concat(seed,salt,round index) */
+ memcpy(cmt_1_i_input[instance] + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ }
+
+ uint8_t cmt_0[T][HASH_DIGEST_LENGTH] = {0};
+ uint8_t cmt_1[T][HASH_DIGEST_LENGTH] = {0};
+
+ FZ_ELEM eta_tilde[N];
+ FQ_ELEM u_tilde[N];
+
+ FQ_ELEM y_tilde[N] = {0};
+ FQ_ELEM s_tilde[N - K] = {0};
+
+ FQ_ELEM y[T][N];
+
+ /* enqueue the calls to hash */
+ int to_hash_cmt_1 = 0;
+ int to_hash_cmt_0 = 0;
+ int round_idx_queue_cmt_1[4] = {0};
+ int round_idx_queue_cmt_0[4] = {0};
+
+ int used_rsps = 0;
+ int is_signature_ok = 1;
+ for (uint16_t i = 0; i < T; i++) {
+
+ /* i+c */
+ uint16_t domain_sep_i = i + NUM_NODES_SEED_TREE;
+ /* i+c+dsc */
+ uint16_t domain_sep_idx_hash = domain_sep_i + HASH_CSPRNG_DOMAIN_SEP_CONST;
+
+ if (fixed_weight_b[i] == 1) {
+
+ /* save the index for the hash output */
+ to_hash_cmt_1++;
+ round_idx_queue_cmt_1[to_hash_cmt_1 - 1] = i;
+
+ memcpy(cmt_1_i_input[to_hash_cmt_1 - 1],
+ rounds_seeds + SEED_LENGTH_BYTES * i,
+ SEED_LENGTH_BYTES);
+
+ cmt_1_i_input[to_hash_cmt_1 - 1][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_1_i_input[to_hash_cmt_1 - 1][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + 1] = domain_sep_idx_hash & 0xFF;
+
+ /* CSPRNG is fed with concat(seed,salt,round index) represented
+ * as a 2 bytes little endian unsigned integer */
+ uint8_t csprng_input[CSPRNG_INPUT_LENGTH];
+ memcpy(csprng_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ memcpy(csprng_input, rounds_seeds + SEED_LENGTH_BYTES * i, SEED_LENGTH_BYTES);
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES] = (domain_sep_i >> 8) & 0xFF;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + 1] = domain_sep_i & 0xFF;
+
+ /* expand seed[i] into seed_e and seed_u */
+ initialize_csprng(&CSPRNG_state, csprng_input, CSPRNG_INPUT_LENGTH);
+ /* expand eta_tilde */
+ CSPRNG_zz_vec(eta_tilde, &CSPRNG_state);
+ /* expand u_tilde */
+ CSPRNG_fq_vec(u_tilde, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ fq_vec_by_restr_vec_scaled(y[i],
+ eta_tilde,
+ beta[i],
+ u_tilde);
+ fq_dz_norm(y[i]);
+ } else {
+
+ /* save the index for the hash output */
+ to_hash_cmt_0++;
+ round_idx_queue_cmt_0[to_hash_cmt_0 - 1] = i;
+
+ /* place y[i] in the buffer for later on hashing */
+ PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fq_vec(y[i], sig->rsp_0[used_rsps].y);
+
+ FZ_ELEM sigma_local[N];
+ /*sigma is memcpy'ed directly into cmt_0 input buffer */
+ FZ_ELEM *sigma_ptr = cmt_0_i_input[to_hash_cmt_0 - 1] + DENSELY_PACKED_FQ_SYN_SIZE;
+ PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fz_vec(sigma_local, sig->rsp_0[used_rsps].sigma);
+ memcpy(sigma_ptr,
+ &sig->rsp_0[used_rsps].sigma,
+ DENSELY_PACKED_FZ_VEC_SIZE);
+ is_signature_ok = is_signature_ok &&
+ is_zz_vec_in_restr_group(sigma_local);
+ memcpy(cmt_1[i], sig->rsp_1[used_rsps], HASH_DIGEST_LENGTH);
+ used_rsps++;
+
+ FQ_ELEM v[N];
+ convert_restr_vec_to_fq(v, sigma_local);
+ fq_vec_by_fq_vec_pointwise(y_tilde, v, y[i]);
+ fq_vec_by_fq_matrix(s_tilde, y_tilde, V_tr_avx);
+ fq_dz_norm_synd(s_tilde);
+ FQ_ELEM to_compress[N - K];
+ fq_synd_minus_fq_vec_scaled(to_compress,
+ s_tilde,
+ beta[i],
+ pub_syn);
+ fq_dz_norm_synd(to_compress);
+ PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_syn(cmt_0_i_input[to_hash_cmt_0 - 1], to_compress);
+ cmt_0_i_input[to_hash_cmt_0 - 1][offset_round_idx] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_0_i_input[to_hash_cmt_0 - 1][offset_round_idx + 1] = domain_sep_idx_hash & 0xFF;
+
+ }
+ /* hash committment 1 in batches of 4 (or less on the last round) */
+ if (to_hash_cmt_1 == 4 || i == T - 1) {
+ par_hash(
+ to_hash_cmt_1,
+ cmt_1[round_idx_queue_cmt_1[0]],
+ cmt_1[round_idx_queue_cmt_1[1]],
+ cmt_1[round_idx_queue_cmt_1[2]],
+ cmt_1[round_idx_queue_cmt_1[3]],
+ cmt_1_i_input[0],
+ cmt_1_i_input[1],
+ cmt_1_i_input[2],
+ cmt_1_i_input[3],
+ sizeof(cmt_1_i_input) / 4
+ );
+ to_hash_cmt_1 = 0;
+ }
+ /* hash committment 0 in batches of 4 (or less on the last round) */
+ if (to_hash_cmt_0 == 4 || i == T - 1) {
+ par_hash(
+ to_hash_cmt_0,
+ cmt_0[round_idx_queue_cmt_0[0]],
+ cmt_0[round_idx_queue_cmt_0[1]],
+ cmt_0[round_idx_queue_cmt_0[2]],
+ cmt_0[round_idx_queue_cmt_0[3]],
+ cmt_0_i_input[0],
+ cmt_0_i_input[1],
+ cmt_0_i_input[2],
+ cmt_0_i_input[3],
+ sizeof(cmt_0_i_input) / 4
+ );
+ to_hash_cmt_0 = 0;
+ }
+ } /* end for iterating on ZKID iterations */
+
+ /* PQClean-edit: remove assertion */
+ //assert(is_signature_ok);
+
+ uint8_t commit_digests[2][HASH_DIGEST_LENGTH];
+ PQCLEAN_CROSSRSDP128FAST_AVX2_merkle_tree_root_recompute(commit_digests[0],
+ cmt_0,
+ sig->mtp,
+ fixed_weight_b);
+ hash(commit_digests[1], (unsigned char *)cmt_1, sizeof(cmt_1));
+
+ uint8_t digest_01_recomputed[HASH_DIGEST_LENGTH];
+ hash(digest_01_recomputed,
+ (unsigned char *) commit_digests,
+ sizeof(commit_digests));
+
+ uint8_t digest_b_buf[T * DENSELY_PACKED_FQ_VEC_SIZE + HASH_DIGEST_LENGTH];
+ for (int x = 0; x < T; x++) {
+ PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_vec(digest_b_buf + (x * DENSELY_PACKED_FQ_VEC_SIZE), y[x]);
+ }
+ memcpy(digest_b_buf + T * DENSELY_PACKED_FQ_VEC_SIZE, d_beta, HASH_DIGEST_LENGTH);
+
+ uint8_t digest_b_recomputed[HASH_DIGEST_LENGTH];
+ hash(digest_b_recomputed, digest_b_buf, sizeof(digest_b_buf));
+
+ int does_digest_01_match = ( memcmp(digest_01_recomputed,
+ sig->digest_01,
+ HASH_DIGEST_LENGTH) == 0);
+ /* PQClean-edit: remove assertion */
+ //assert(does_digest_01_match);
+
+ int does_digest_b_match = ( memcmp(digest_b_recomputed,
+ sig->digest_b,
+ HASH_DIGEST_LENGTH) == 0);
+ /* PQClean-edit: remove assertion */
+ //assert(does_digest_b_match);
+
+ is_signature_ok = is_signature_ok &&
+ does_digest_01_match &&
+ does_digest_b_match;
+ return is_signature_ok;
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/CROSS.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/CROSS.h
new file mode 100644
index 000000000..47d73b422
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/CROSS.h
@@ -0,0 +1,74 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+#pragma once
+
+#include
+
+#include "pack_unpack.h"
+#include "parameters.h"
+
+/* Public key: the parity check matrix is shrunk to a seed, syndrome
+ * represented in full */
+typedef struct {
+ uint8_t seed_pub[KEYPAIR_SEED_LENGTH_BYTES];
+ uint8_t s[DENSELY_PACKED_FQ_SYN_SIZE];
+} pubkey_t;
+
+/* Private key: just a single seed*/
+typedef struct {
+ uint8_t seed[KEYPAIR_SEED_LENGTH_BYTES];
+} prikey_t;
+
+typedef struct {
+ uint8_t y[DENSELY_PACKED_FQ_VEC_SIZE];
+ uint8_t sigma[DENSELY_PACKED_FZ_VEC_SIZE];
+} rsp_0_t;
+
+/* Signature: */
+typedef struct {
+ uint8_t salt[SALT_LENGTH_BYTES];
+ uint8_t digest_01[HASH_DIGEST_LENGTH];
+ uint8_t digest_b[HASH_DIGEST_LENGTH];
+ uint8_t stp[W * SEED_LENGTH_BYTES];
+ uint8_t mtp[W * HASH_DIGEST_LENGTH];
+ rsp_0_t rsp_0[T - W];
+ uint8_t rsp_1[T - W][HASH_DIGEST_LENGTH];
+} CROSS_sig_t;
+
+/* keygen cannot fail */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_CROSS_keygen(prikey_t *SK,
+ pubkey_t *PK);
+
+/* sign cannot fail */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_CROSS_sign(const prikey_t *SK,
+ const char *m,
+ size_t mlen,
+ CROSS_sig_t *sig);
+
+/* verify returns 1 if signature is ok, 0 otherwise */
+int PQCLEAN_CROSSRSDP128FAST_AVX2_CROSS_verify(const pubkey_t *PK,
+ const char *m,
+ size_t mlen,
+ const CROSS_sig_t *sig);
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/LICENSE b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/LICENSE
new file mode 100644
index 000000000..0e259d42c
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/LICENSE
@@ -0,0 +1,121 @@
+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/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/api.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/api.h
new file mode 100644
index 000000000..3e0e807a7
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/api.h
@@ -0,0 +1,80 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#ifndef PQCLEAN_CROSSRSDP128FAST_AVX2_API_H
+#define PQCLEAN_CROSSRSDP128FAST_AVX2_API_H
+
+#pragma once
+
+#include
+#include
+
+#define PQCLEAN_CROSSRSDP128FAST_AVX2_CRYPTO_ALGNAME "cross-rsdp-128-fast"
+
+/* no. of bytes of the secret key */
+#define PQCLEAN_CROSSRSDP128FAST_AVX2_CRYPTO_SECRETKEYBYTES 32
+
+/* no. of bytes of the public key */
+#define PQCLEAN_CROSSRSDP128FAST_AVX2_CRYPTO_PUBLICKEYBYTES 77
+
+/* no. of bytes of overhead in a signed message */
+#define PQCLEAN_CROSSRSDP128FAST_AVX2_CRYPTO_BYTES 19152
+
+/* required bytes of input randomness */
+#define PQCLEAN_CROSSRSDP128FAST_AVX2_CRYPTO_RANDOMBYTES 16
+
+int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_keypair(unsigned char *pk,
+ unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign(unsigned char *sm,
+ size_t *smlen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_open(unsigned char *m,
+ size_t *mlen,
+ const unsigned char *sm,
+ size_t smlen,
+ const unsigned char *pk
+ );
+
+int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_signature(unsigned char *sig,
+ size_t *siglen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_verify(const unsigned char *sig,
+ size_t siglen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *pk
+ );
+
+#endif
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/architecture_detect.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/architecture_detect.h
new file mode 100644
index 000000000..6372cedc3
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/architecture_detect.h
@@ -0,0 +1,13 @@
+
+#pragma once
+
+/* liboqs-edit: avoid checking for ISA extensions
+ * when compiling avx2 just assume that Intel Instrinsics are available */
+#include
+#include
+#include
+#include
+//#include // liboqs-edit: x86intrin.h is not available on Windows
+
+#define EPI8_PER_REG 32
+#define EPI16_PER_REG 16
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/csprng_hash.c b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/csprng_hash.c
new file mode 100644
index 000000000..382354ea9
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/csprng_hash.c
@@ -0,0 +1,82 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include
+
+#include "csprng_hash.h"
+
+#define POSITION_MASK (( (uint16_t)1 << BITS_TO_REPRESENT(T-1))-1)
+
+/* Fisher-Yates shuffle obtaining the entire required randomness in a single
+ * call */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_expand_digest_to_fixed_weight(uint8_t fixed_weight_string[T],
+ const uint8_t digest[HASH_DIGEST_LENGTH]) {
+ CSPRNG_STATE_T csprng_state;
+ initialize_csprng(&csprng_state,
+ (const unsigned char *) digest,
+ HASH_DIGEST_LENGTH);
+ uint8_t CSPRNG_buffer[ROUND_UP(BITS_CWSTR_RNG, 8) / 8];
+ csprng_randombytes(CSPRNG_buffer, ROUND_UP(BITS_CWSTR_RNG, 8) / 8, &csprng_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&csprng_state);
+
+ /* initialize CW string */
+ memset(fixed_weight_string, 1, W);
+ memset(fixed_weight_string + W, 0, T - W);
+
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ int pos_in_buf = 8;
+
+ int curr = 0;
+ while (curr < T) {
+ /* refill randomness buffer if needed */
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ /*we need to draw a number in 0... T-1-curr */
+ int bits_for_pos = BITS_TO_REPRESENT(T - 1 - curr);
+ uint64_t pos_mask = ( (uint64_t) 1 << bits_for_pos) - 1;
+ uint16_t candidate_pos = (sub_buffer & pos_mask);
+ if (candidate_pos < T - curr) {
+ int dest = curr + candidate_pos;
+ /* the position is admissible, swap */
+ uint8_t tmp = fixed_weight_string[curr];
+ fixed_weight_string[curr] = fixed_weight_string[dest];
+ fixed_weight_string[dest] = tmp;
+ curr++;
+ sub_buffer = sub_buffer >> bits_for_pos;
+ bits_in_sub_buf -= bits_for_pos;
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+} /* PQCLEAN_CROSSRSDP128FAST_AVX2_expand_digest_to_fixed_weight */
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/csprng_hash.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/csprng_hash.h
new file mode 100644
index 000000000..0aae75c2f
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/csprng_hash.h
@@ -0,0 +1,420 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+#pragma once
+
+#include "parameters.h"
+#include "sha3.h"
+
+/************************* CSPRNG ********************************/
+
+#define CSPRNG_STATE_T SHAKE_STATE_STRUCT
+/* initializes a CSPRNG, given the seed and a state pointer */
+static inline
+void initialize_csprng(CSPRNG_STATE_T *const csprng_state,
+ const unsigned char *const seed,
+ const uint32_t seed_len_bytes) {
+ // the second parameter is the security level of the SHAKE instance
+ xof_shake_init(csprng_state, SEED_LENGTH_BYTES * 8);
+ xof_shake_update(csprng_state, seed, seed_len_bytes);
+ xof_shake_final(csprng_state);
+} /* end initialize_csprng */
+
+/* extracts xlen bytes from the CSPRNG, given the state */
+static inline
+void csprng_randombytes(unsigned char *const x,
+ uint64_t xlen,
+ CSPRNG_STATE_T *const csprng_state) {
+ xof_shake_extract(csprng_state, x, xlen);
+}
+
+/* PQClean-edit: CSPRNG release context */
+static inline
+void csprng_release(CSPRNG_STATE_T *const csprng_state) {
+ xof_shake_release(csprng_state);
+}
+
+/**************** Parallel CSPRNG (x2, x3, x4) ***********************/
+
+#define CSPRNG_X2_STATE_T SHAKE_X2_STATE_STRUCT
+/* CRSPRNG_x3 calls SHAKE_x4 and discards the fourth input/output */
+#define CSPRNG_X3_STATE_T SHAKE_X4_STATE_STRUCT
+#define CSPRNG_X4_STATE_T SHAKE_X4_STATE_STRUCT
+
+/* initialize */
+static inline
+void initialize_csprng_x2(CSPRNG_X2_STATE_T *const csprng_state, const unsigned char *const seed1, const unsigned char *const seed2, const uint32_t seed_len_bytes) {
+ xof_shake_x2_init(csprng_state);
+ xof_shake_x2_update(csprng_state, seed1, seed2, seed_len_bytes);
+ xof_shake_x2_final(csprng_state);
+}
+static inline
+void initialize_csprng_x3(CSPRNG_X3_STATE_T *const csprng_state, const unsigned char *const seed1, const unsigned char *const seed2, const unsigned char *const seed3, const uint32_t seed_len_bytes) {
+ /* to perform xof_x3 it's faster to call xof_x4 and discard the last output */
+ xof_shake_x4_init(csprng_state);
+ xof_shake_x4_update(csprng_state, seed1, seed2, seed3, seed3, seed_len_bytes);
+ xof_shake_x4_final(csprng_state);
+}
+static inline
+void initialize_csprng_x4(CSPRNG_X4_STATE_T *const csprng_state, const unsigned char *const seed1, const unsigned char *const seed2, const unsigned char *const seed3, const unsigned char *const seed4, const uint32_t seed_len_bytes) {
+ xof_shake_x4_init(csprng_state);
+ xof_shake_x4_update(csprng_state, seed1, seed2, seed3, seed4, seed_len_bytes);
+ xof_shake_x4_final(csprng_state);
+}
+/* randombytes */
+static inline
+void csprng_randombytes_x2(unsigned char *const x1, unsigned char *const x2, uint64_t xlen, CSPRNG_X2_STATE_T *const csprng_state) {
+ xof_shake_x2_extract(csprng_state, x1, x2, xlen);
+}
+static inline
+void csprng_randombytes_x3(unsigned char *const x1, unsigned char *const x2, unsigned char *const x3, uint64_t xlen, CSPRNG_X3_STATE_T *const csprng_state) {
+ /* to perform xof_x3 it's faster to call xof_x4 and discard the last output */
+ xof_shake_x4_extract(csprng_state, x1, x2, x3, x3, xlen);
+}
+static inline
+void csprng_randombytes_x4(unsigned char *const x1, unsigned char *const x2, unsigned char *const x3, unsigned char *const x4, uint64_t xlen, CSPRNG_X4_STATE_T *const csprng_state) {
+ xof_shake_x4_extract(csprng_state, x1, x2, x3, x4, xlen);
+}
+/* release */
+static inline
+void csprng_release_x2(CSPRNG_X2_STATE_T *const csprng_state) {
+ xof_shake_x2_release(csprng_state);
+}
+static inline
+void csprng_release_x3(CSPRNG_X3_STATE_T *const csprng_state) {
+ xof_shake_x4_release(csprng_state);
+}
+static inline
+void csprng_release_x4(CSPRNG_X4_STATE_T *const csprng_state) {
+ xof_shake_x4_release(csprng_state);
+}
+
+/************** Single API for Parallel CSPRNG *******************/
+
+#define PAR_CSPRNG_STATE_T par_shake_ctx
+
+static inline
+void par_initialize_csprng(int par_level, PAR_CSPRNG_STATE_T *const states, const unsigned char *const seed1, const unsigned char *const seed2, const unsigned char *const seed3, const unsigned char *const seed4, const uint32_t seed_len_bytes) {
+ if (par_level == 1) {
+ initialize_csprng(&(states->state1), seed1, seed_len_bytes);
+ } else if (par_level == 2) {
+ initialize_csprng_x2(&(states->state2), seed1, seed2, seed_len_bytes);
+ } else if (par_level == 3) {
+ initialize_csprng_x3(&(states->state4), seed1, seed2, seed3, seed_len_bytes);
+ } else if (par_level == 4) {
+ initialize_csprng_x4(&(states->state4), seed1, seed2, seed3, seed4, seed_len_bytes);
+ }
+}
+static inline
+void par_csprng_randombytes(int par_level, PAR_CSPRNG_STATE_T *const states, unsigned char *const x1, unsigned char *const x2, unsigned char *const x3, unsigned char *const x4, uint64_t xlen) {
+ if (par_level == 1) {
+ csprng_randombytes(x1, xlen, &(states->state1));
+ } else if (par_level == 2) {
+ csprng_randombytes_x2(x1, x2, xlen, &(states->state2));
+ } else if (par_level == 3) {
+ csprng_randombytes_x3(x1, x2, x3, xlen, &(states->state4));
+ } else if (par_level == 4) {
+ csprng_randombytes_x4(x1, x2, x3, x4, xlen, &(states->state4));
+ }
+}
+static inline
+void par_csprng_release(int par_level, PAR_CSPRNG_STATE_T *const states) {
+ if (par_level == 1) {
+ csprng_release(&(states->state1));
+ } else if (par_level == 2) {
+ csprng_release_x2(&(states->state2));
+ } else if (par_level == 3) {
+ csprng_release_x3(&(states->state4));
+ } else if (par_level == 4) {
+ csprng_release_x4(&(states->state4));
+ }
+}
+
+/******************************************************************************/
+
+/* PQClean-edit: remove randombytes definition here to use PQClean randombytes */
+//static inline void randombytes(unsigned char * x, uint64_t xlen) ...
+
+/************************* HASH functions ********************************/
+
+/* Opaque algorithm agnostic hash call */
+static inline
+void hash(uint8_t digest[HASH_DIGEST_LENGTH],
+ const unsigned char *const m,
+ const uint64_t mlen) {
+ /* SHAKE with a 2*lambda bit digest is employed also for hashing */
+ CSPRNG_STATE_T csprng_state;
+ xof_shake_init(&csprng_state, SEED_LENGTH_BYTES * 8);
+ xof_shake_update(&csprng_state, m, mlen);
+ xof_shake_final(&csprng_state);
+ xof_shake_extract(&csprng_state, digest, HASH_DIGEST_LENGTH);
+ /* PQClean-edit: CSPRNG release context */
+ xof_shake_release(&csprng_state);
+}
+
+#define par_xof_input par_initialize_csprng
+#define par_xof_output par_csprng_randombytes
+#define par_xof_release par_csprng_release
+
+static inline
+void par_hash(
+ int par_level,
+ uint8_t digest_1[HASH_DIGEST_LENGTH],
+ uint8_t digest_2[HASH_DIGEST_LENGTH],
+ uint8_t digest_3[HASH_DIGEST_LENGTH],
+ uint8_t digest_4[HASH_DIGEST_LENGTH],
+ const unsigned char *const m_1,
+ const unsigned char *const m_2,
+ const unsigned char *const m_3,
+ const unsigned char *const m_4,
+ const uint64_t mlen) {
+ PAR_CSPRNG_STATE_T states;
+ par_xof_input(par_level, &states, m_1, m_2, m_3, m_4, mlen);
+ par_xof_output(par_level, &states, digest_1, digest_2, digest_3, digest_4, HASH_DIGEST_LENGTH);
+ par_xof_release(par_level, &states);
+}
+
+/********************** CSPRNG Sampling functions helpers ********************/
+
+static inline
+FQ_ELEM fq_star_rnd_state(CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_TO_REPRESENT(Q - 2) ) - 1;
+ FQ_ELEM rnd_value;
+ do {
+ csprng_randombytes((unsigned char *) &rnd_value,
+ sizeof(FQ_ELEM),
+ csprng_state);
+ rnd_value = mask & rnd_value;
+ } while (rnd_value > Q - 2);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(csprng_state);
+
+ return rnd_value + 1;
+} /* end fq_star_rnd_state */
+
+/***************** Specialized CSPRNGs for non binary domains *****************/
+
+/* CSPRNG sampling fixed weight strings */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_expand_digest_to_fixed_weight(uint8_t fixed_weight_string[T],
+ const uint8_t digest[HASH_DIGEST_LENGTH]);
+
+#define BITS_FOR_Q BITS_TO_REPRESENT(Q-1)
+#define BITS_FOR_Z BITS_TO_REPRESENT(Z-1)
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_FQ_VEC ((BITS_N_ZQ_CT_RNG - N*BITS_FOR_Q)* (BITS_FOR_Q-1))
+#define BUFSIZE_FQ_VEC (ROUND_UP(BITS_N_ZQ_CT_RNG+CORRECTION_FQ_VEC,8)/8)
+
+static inline
+void CSPRNG_fq_vec(FQ_ELEM res[N],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_FOR_Q) - 1;
+ /* NOTE: Current bit cost estimation technique underestimates the failures
+ * whenever they appear in a run; an upper bound on the bit-cost is considering
+ * the failures to be discarding the entire value, instead of a single bit.
+ * The following correction factor takes this into account */
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_N_ZQ_CT_RNG - N*BITS_FOR_Q)* (BITS_FOR_Q-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_N_ZQ_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_FQ_VEC];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right, shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_FQ_VEC, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+ while (placed < N) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ res[placed] = sub_buffer & mask;
+ if (res[placed] < Q) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Q;
+ bits_in_sub_buf -= BITS_FOR_Q;
+
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
+
+#define BITS_FOR_Q_M_ONE BITS_TO_REPRESENT(Q-2)
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_FQ_VEC_BETA ((BITS_BETA_ZQSTAR_CT_RNG - T*BITS_FOR_Q_M_ONE) * (BITS_FOR_Q_M_ONE-1))
+#define BUFSIZE_FQ_VEC_BETA (ROUND_UP(BITS_BETA_ZQSTAR_CT_RNG+CORRECTION_FQ_VEC_BETA,8)/8)
+
+static inline
+void CSPRNG_fq_vec_beta(FQ_ELEM res[T],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_FOR_Q_M_ONE) - 1;
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_BETA_ZQSTAR_CT_RNG - T*BITS_FOR_Q_M_ONE) * (BITS_FOR_Q_M_ONE-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_BETA_ZQSTAR_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_FQ_VEC_BETA];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right , shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_FQ_VEC_BETA, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+ while (placed < T) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ /* draw from 0 ... Q-2, then add 1*/
+ res[placed] = (sub_buffer & mask) + 1;
+ if (res[placed] < Q) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Q_M_ONE;
+ bits_in_sub_buf -= BITS_FOR_Q_M_ONE;
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_FQ_MAT ((BITS_V_CT_RNG - K*(N-K)*BITS_FOR_Q) * (BITS_FOR_Q-1))
+#define BUFSIZE_FQ_MAT (ROUND_UP(BITS_V_CT_RNG+CORRECTION_FQ_MAT,8)/8)
+
+static inline
+void CSPRNG_fq_mat(FQ_ELEM res[K][N - K],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FQ_ELEM mask = ( (FQ_ELEM) 1 << BITS_FOR_Q) - 1;
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_V_CT_RNG - K*(N-K)*BITS_FOR_Q) * (BITS_FOR_Q-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_V_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_FQ_MAT];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right , shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_FQ_MAT, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+
+ while (placed < K * (N - K)) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ *( (FQ_ELEM *)res + placed) = sub_buffer & mask;
+ if (*( (FQ_ELEM *)res + placed) < Q) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Q;
+ bits_in_sub_buf -= BITS_FOR_Q;
+
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
+
+/* PQClean-edit: avoid VLA */
+#define CORRECTION_ZZ_VEC ((BITS_N_ZZ_CT_RNG - N*BITS_FOR_Z) * (BITS_FOR_Z-1))
+#define BUFSIZE_ZZ_VEC ROUND_UP(BITS_N_ZZ_CT_RNG+CORRECTION_ZZ_VEC,8)/8
+
+static inline
+void CSPRNG_zz_vec(FZ_ELEM res[N],
+ CSPRNG_STATE_T *const csprng_state) {
+ const FZ_ELEM mask = ( (FZ_ELEM) 1 << BITS_FOR_Z) - 1;
+
+ /* PQClean-edit: avoid VLA */
+ //uint32_t correction_bit_len = (BITS_N_ZZ_CT_RNG - N*BITS_FOR_Z) * (BITS_FOR_Z-1);
+ //uint32_t CSPRNG_buffer_size = ROUND_UP(BITS_N_ZZ_CT_RNG+correction_bit_len,8)/8;
+ //uint8_t CSPRNG_buffer[ROUND_UP(CSPRNG_buffer_size,4)];
+ uint8_t CSPRNG_buffer[BUFSIZE_ZZ_VEC];
+
+ /* To facilitate hardware implementations, the uint64_t
+ * sub-buffer is consumed starting from the least significant byte
+ * i.e., from the first being output by SHAKE. Bits in the byte are
+ * discarded shifting them out to the right , shifting fresh ones
+ * in from the left end */
+ csprng_randombytes(CSPRNG_buffer, BUFSIZE_ZZ_VEC, csprng_state);
+ int placed = 0;
+ uint64_t sub_buffer = *(uint64_t *)CSPRNG_buffer;
+ int bits_in_sub_buf = 64;
+ /* position of the next fresh byte in CSPRNG_buffer*/
+ int pos_in_buf = 8;
+ while (placed < N) {
+ if (bits_in_sub_buf <= 32) {
+ /* get 32 fresh bits from main buffer with a single load */
+ uint32_t refresh_buf = *(uint32_t *) (CSPRNG_buffer + pos_in_buf);
+ pos_in_buf += 4;
+ sub_buffer |= ((uint64_t) refresh_buf) << bits_in_sub_buf;
+ bits_in_sub_buf += 32;
+ }
+ /* get */
+ res[placed] = sub_buffer & mask;
+ if (res[placed] < Z) {
+ placed++;
+ sub_buffer = sub_buffer >> BITS_FOR_Z;
+ bits_in_sub_buf -= BITS_FOR_Z;
+
+ } else {
+ sub_buffer = sub_buffer >> 1;
+ bits_in_sub_buf -= 1;
+ }
+ }
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/fq_arith.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/fq_arith.h
new file mode 100644
index 000000000..f30ac9702
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/fq_arith.h
@@ -0,0 +1,225 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include
+#include
+#include
+
+#include "architecture_detect.h"
+#include "csprng_hash.h"
+#include "parameters.h"
+#include "restr_arith.h"
+
+#define NUM_BITS_Q (BITS_TO_REPRESENT(Q))
+
+#define FQRED_SINGLE(x) (((x) & 0x7F) + ((x) >> 7))
+#define FQRED_DOUBLE(x) FQRED_SINGLE(FQRED_SINGLE(x))
+#define FQRED_OPPOSITE(x) ((x) ^ 0x7F)
+#define FQ_DOUBLE_ZERO_NORM(x) (((x) + (((x) + 1) >> 7)) & 0x7F)
+#define RESTR_TO_VAL(x) ( (FQ_ELEM) (RESTR_G_TABLE >> (8*(uint64_t)(x))) )
+
+/* in-place normalization of redundant zero representation for syndromes*/
+static inline
+void fq_dz_norm_synd(FQ_ELEM v[N - K]) {
+ for (int i = 0; i < N - K; i++) {
+ v[i] = FQ_DOUBLE_ZERO_NORM(v[i]);
+ }
+}
+
+static inline
+void fq_dz_norm(FQ_ELEM v[N]) {
+ for (int i = 0; i < N; i++) {
+ v[i] = FQ_DOUBLE_ZERO_NORM(v[i]);
+ }
+}
+
+/* Computes the product e*H of an n-element restricted vector by a (n-k)*n
+ * F_q H is in systematic form. Only the non systematic portion of H =[V I],
+ * V, is provided, transposed, hence linearized by columns so that syndrome
+ * computation is vectorizable. */
+/* Used by keygen */
+static
+void restr_vec_by_fq_matrix(FQ_ELEM res[N - K],
+ const FZ_ELEM e[N],
+ FQ_ELEM V_tr[K][N - K]) {
+ FQ_DOUBLEPREC res_dprec[N - K] = {0};
+ for (int i = 0; i < N - K; i++) {
+ res_dprec[i] = RESTR_TO_VAL(e[K + i]);
+ }
+ for (int i = 0; i < K; i++) {
+ for (int j = 0; j < N - K; j++) {
+ res_dprec[j] += FQRED_SINGLE(
+ (FQ_DOUBLEPREC) RESTR_TO_VAL(e[i]) *
+ (FQ_DOUBLEPREC) V_tr[i][j]);
+ if (i == Q - 1) {
+ res_dprec[j] = FQRED_SINGLE(res_dprec[j]);
+ }
+ }
+ }
+ /* Save result trimming to regular precision */
+ for (int i = 0; i < N - K; i++) {
+ res[i] = FQRED_SINGLE(res_dprec[i]);
+ }
+}
+
+/* Computes e * [I_k V]^T, V is already in transposed form
+ * since */
+static
+void fq_vec_by_fq_matrix(FQ_ELEM res[N - K],
+ const FQ_ELEM e[N],
+ FQ_DOUBLEPREC V_tr[K][ROUND_UP(N - K, EPI16_PER_REG)]) {
+
+ alignas(EPI8_PER_REG) FQ_DOUBLEPREC res_dprec[ROUND_UP(N - K, EPI16_PER_REG)] = {0};
+ for (int i = 0; i < N - K; i++) {
+ res_dprec[i] = e[K + i];
+ }
+ __m256i mred_mask = _mm256_set1_epi16 (0x007f);
+
+ for (int i = 0; i < K; i++) {
+ for (int j = 0; j < ROUND_UP(N - K, EPI16_PER_REG) / EPI16_PER_REG; j++) {
+ __m256i res_w = _mm256_load_si256(
+ (__m256i const *) &res_dprec[j * EPI16_PER_REG] );
+ __m256i e_coeff = _mm256_set1_epi16(e[i]);
+ __m256i V_tr_slice = _mm256_lddqu_si256(
+ (__m256i const *) &V_tr[i][j * EPI16_PER_REG] );
+ __m256i tmp = _mm256_mullo_epi16(e_coeff, V_tr_slice);
+ /* Vector Mersenne reduction */
+ __m256i tmp2 = _mm256_and_si256 (tmp, mred_mask);
+ tmp = _mm256_srli_epi16(tmp, 7);
+ tmp = _mm256_add_epi16(tmp, tmp2);
+ res_w = _mm256_add_epi16(res_w, tmp);
+ /* store back*/
+ _mm256_store_si256 ((__m256i *) &res_dprec[j * EPI16_PER_REG], res_w);
+ }
+ }
+ /* Save result trimming to regular precision */
+ for (int i = 0; i < N - K; i++) {
+ res[i] = FQRED_DOUBLE(res_dprec[i]);
+ }
+}
+
+static inline
+void fq_vec_by_fq_vec_pointwise(FQ_ELEM res[N],
+ const FQ_ELEM in1[N],
+ const FQ_ELEM in2[N]) {
+ for (int i = 0; i < N; i++) {
+ res[i] = FQRED_SINGLE( (FQ_DOUBLEPREC) in1[i] *
+ (FQ_DOUBLEPREC) in2[i] );
+ }
+}
+
+static inline
+void restr_by_fq_vec_pointwise(FQ_ELEM res[N],
+ const FZ_ELEM in1[N],
+ const FQ_ELEM in2[N]) {
+ for (int i = 0; i < N; i++) {
+ res[i] = FQRED_SINGLE( (FQ_DOUBLEPREC) RESTR_TO_VAL(in1[i]) *
+ (FQ_DOUBLEPREC) in2[i]);
+ }
+}
+
+/* e*beta + u_tilde*/
+static inline
+void fq_vec_by_restr_vec_scaled(FQ_ELEM res[N],
+ const FZ_ELEM e[N],
+ const FQ_ELEM beta,
+ const FQ_ELEM u_tilde[N]) {
+
+ alignas(EPI8_PER_REG) FZ_ELEM e_align[ROUND_UP(N, EPI8_PER_REG)];
+ alignas(EPI8_PER_REG) FQ_ELEM utilde_align[ROUND_UP(N, EPI8_PER_REG)];
+ alignas(EPI8_PER_REG) FQ_ELEM res_align[ROUND_UP(N, EPI8_PER_REG)];
+ __m256i mred_mask = _mm256_set1_epi16 ((uint16_t)0x007f);
+ __m256i dense_mred_mask = _mm256_set1_epi8 ((uint8_t)0x7f);
+ __m256i dense_neg_mred_mask = _mm256_set1_epi8 ((uint8_t)0x80);
+ memcpy(e_align, e, N);
+ memcpy(utilde_align, u_tilde, N);
+
+ /* set a register with beta, EPI16_PER_REG times */
+ __m256i beta_comb = _mm256_set1_epi16 ((uint16_t) beta);
+
+ /* Since the single-cycle shuffle acts only on 128b lanes separately,
+ * prepare two pairs of tables, with alternating scattered elements, to be
+ * broadcast-multiplied. Results are then reduced, and byte packed again
+ * to allow the use of the shuffle instruction */
+ __m256i LUT_sparse = _mm256_set_epi16 (0x0001, 0x0020, 0x0008, 0x0002,
+ 0x0040, 0x0010, 0x0004, 0x0001,
+ 0x0001, 0x0020, 0x0008, 0x0002,
+ 0x0040, 0x0010, 0x0004, 0x0001);
+
+ /* comb-multiply the lookup table made of a single register obtaining
+ * pre-scaled values */
+ LUT_sparse = _mm256_mullo_epi16(LUT_sparse, beta_comb);
+ /* Vector Mersenne reduction */
+ __m256i tmp = _mm256_and_si256 (LUT_sparse, mred_mask);
+ LUT_sparse = _mm256_srli_epi16(LUT_sparse, 7);
+ LUT_sparse = _mm256_add_epi16(tmp, LUT_sparse);
+ /*semantics from the manual call for a *byte amount* in _mm256_srli_si256*/
+ tmp = _mm256_srli_si256(LUT_sparse, 7);
+ LUT_sparse = _mm256_or_si256(LUT_sparse, tmp);
+
+ /* Convert restricted to rescaled values by batch exponentiating them
+ * via shuffle: "shuffling" the table according to the restricted values
+ * yields beta-multiplied elements of F_q*/
+ for (int i = 0; i < ROUND_UP(N, EPI8_PER_REG) / EPI8_PER_REG; i++ ) {
+ __m256i e_word = _mm256_load_si256( (__m256i const *) &e_align[i * EPI8_PER_REG]);
+ e_word = _mm256_shuffle_epi8(LUT_sparse, e_word);
+ /* add to u tilde */
+ __m256i utilde_word = _mm256_load_si256( (__m256i const *) &utilde_align[i * EPI8_PER_REG]);
+ __m256i res_word = _mm256_add_epi8(e_word, utilde_word);
+ /* reduce, knowing that a single out bit is the max overflow */
+ tmp = _mm256_and_si256 (res_word, dense_mred_mask);
+ /* no _mm256_srli_epi8 available, cope with the lack hand-clearing
+ * all other bits before shifting */
+ res_word = _mm256_srli_epi16(
+ _mm256_and_si256(res_word, dense_neg_mred_mask),
+ 7);
+ res_word = _mm256_add_epi8(res_word, tmp);
+ _mm256_store_si256 ((__m256i *) &res_align[i * EPI8_PER_REG], res_word);
+
+ }
+ memcpy(res, res_align, N);
+}
+
+static inline
+void fq_synd_minus_fq_vec_scaled(FQ_ELEM res[N - K],
+ const FQ_ELEM synd[N - K],
+ const FQ_ELEM beta,
+ const FQ_ELEM s[N - K]) {
+ for (int j = 0; j < N - K; j++) {
+ FQ_ELEM tmp = FQRED_SINGLE( (FQ_DOUBLEPREC) s[j] * (FQ_DOUBLEPREC) beta);
+ tmp = FQ_DOUBLE_ZERO_NORM(tmp);
+ res[j] = FQRED_SINGLE( (FQ_DOUBLEPREC) synd[j] + FQRED_OPPOSITE(tmp) );
+ }
+}
+
+static inline
+void convert_restr_vec_to_fq(FQ_ELEM res[N],
+ const FZ_ELEM in[N]) {
+ for (int j = 0; j < N; j++) {
+ res[j] = RESTR_TO_VAL(in[j]);
+ }
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/merkle.c b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/merkle.c
new file mode 100644
index 000000000..1aa7c77a8
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/merkle.c
@@ -0,0 +1,399 @@
+/*
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (May 2023)
+ *
+ * @author: Patrick Karl
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+#include
+
+#include "merkle.h"
+
+#define LEAVES_FULL_TREE(L) ( (1UL << LOG2(L) ) )
+#define LEAVES_HALF_TREE(L) ( (LEAVES_FULL_TREE(L) >> 1) )
+
+#define PARENT(i) ( ((i)%2) ? (((i)-1)/2) : (((i)-2)/2) )
+#define RIGHT_CHILD(i) ( (2*(i)+2) )
+#define LEFT_CHILD(i) ( (2*(i)+1) )
+#define SIBLING(i) ( ((i)%2) ? (i)+1 : (i)-1 )
+
+#define RL(i) ((i)==1 ? r_node : l_node)
+#define OFFSET(i) ( (i)*HASH_DIGEST_LENGTH )
+
+#define CHALLENGE_PROOF_VALUE 0
+#define INVALID_MERKLE_NODE 0
+#define VALID_MERKLE_NODE 1
+
+#define NOT_COMPUTED 0
+#define COMPUTED 1
+
+/* maximum number of parallel executions of the hash function */
+#define PAR_DEGREE 4
+
+/*
+ * setup_tree()
+ *
+ * uint16_t layer_offset[LOG2(T)+1] : Stores one offset per layer for layer change.
+ * Required for the computation of PARENT and CHILD nodes.
+ * uint16_t nodes_per_layer[LOG2(T)+1] : Stores the numbers of nodes used in the truncated Merkle tree.
+ */
+static
+void setup_tree(uint16_t layer_offsets[LOG2(T) + 1],
+ uint16_t nodes_per_layer[LOG2(T) + 1]) {
+ uint32_t depth, layer;
+ uint32_t r_leaves;
+ int subtree_found;
+
+ /* Initialize array with full node counts */
+ for (size_t i = 0; i < LOG2(T) + 1; i++) {
+ layer_offsets[i] = (1UL << i);
+ }
+
+ /* Count root node */
+ layer = 0;
+ layer_offsets[layer] -= 1;
+
+ /* Count left tree nodes (always full) */
+ for (size_t i = 1; i < LOG2(T) + 1; i++) {
+ layer_offsets[i] -= (1UL << (i - 1));
+ }
+
+ /* Check every full subtree on right side and subtract missing nodes */
+ r_leaves = T - (1UL << (LOG2(T) - 1));
+ layer = 1;
+ while (r_leaves > 0) {
+ depth = 0;
+ subtree_found = 0;
+ while ( !subtree_found ) {
+ if (r_leaves <= (1UL << depth)) {
+ for (int i = depth; i > 0; i--) {
+ layer_offsets[layer + i] -= (1UL << (i - 1));
+ }
+ r_leaves -= LEAVES_HALF_TREE(r_leaves);
+ layer_offsets[layer] -= 1;
+ layer++;
+ subtree_found = 1;
+ } else {
+ depth++;
+ }
+ }
+ }
+
+ /* For the offset, subtract all missing nodes from previous layers from current layer */
+ for (int i = LOG2(T); i >= 0; i--) {
+ nodes_per_layer[i] = (1UL << i) - layer_offsets[i];
+ for (int j = i - 1; j >= 0; j--) {
+ layer_offsets[i] -= layer_offsets[j];
+ }
+ layer_offsets[i] >>= 1;
+ }
+}
+
+/*
+ * get_leaf_indices() is quite similar to setup_tree(), however requires the
+ * offset values to compute the correct indices.
+ *
+ * uint16_t merkle_leaf_indices[T] : Stores the indices in the truncated tree
+ * where the leaves are placed.
+ * uint16_t layer_offsets[LOG2(T)+1] : Same as above.
+ */
+static
+void get_leaf_indices(uint16_t merkle_leaf_indices[T],
+ const uint16_t layer_offsets[LOG2(T) + 1]) {
+ uint32_t r_leaves;
+ uint32_t idx_ctr = 0;
+
+ /* r_node: current root node of next subtree, will always be right-child of previous root */
+ /* l_node: traverses from current root node to left-childs until depth of subtree is found */
+ uint32_t r_node, l_node;
+ uint32_t layer, depth, subtree_found;
+
+ /* If tree is already balanced, simply copy leaves to corresponding position */
+ if (T == (1UL << LOG2(T))) {
+ for (size_t i = 0; i < T; i++) {
+ merkle_leaf_indices[i] = T - 1 + i;
+ }
+ return;
+ }
+
+ /* Create (un-) balanced Merkle tree */
+ r_leaves = T;
+ depth = 0;
+ layer = 0;
+ r_node = 0;
+ l_node = LEFT_CHILD(r_node) - 2 * layer_offsets[layer + depth];
+ while (r_leaves > 0) {
+ depth = 1;
+ subtree_found = 0;
+ /* Start from the current root node r_node until the size of a full left-subtree is found. */
+ /* If only one leaf is remaining, put it to current root-node, macro RL() is used to decide that. */
+ while ( !subtree_found ) {
+ if (r_leaves <= (1UL << depth)) {
+ for (size_t j = 0; j < LEAVES_HALF_TREE(r_leaves); j++) {
+ merkle_leaf_indices[idx_ctr++] = RL(r_leaves) + j;
+ }
+ r_node = RIGHT_CHILD(r_node) - 2 * layer_offsets[layer];
+ l_node = LEFT_CHILD(r_node) - 2 * layer_offsets[layer];
+ layer++;
+ r_leaves -= LEAVES_HALF_TREE(r_leaves);
+ subtree_found = 1;
+ } else {
+ l_node = LEFT_CHILD(l_node) - 2 * layer_offsets[layer + depth];
+ depth++;
+ }
+ }
+ }
+}
+
+/* PQCLEAN_CROSSRSDP128FAST_AVX2_generate_merkle_tree()
+ *
+ * unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH] :
+ * stores the hashes of the associated tree nodes.
+ * const unsigned char commitments[T][HASH_DIGEST_LENGTH] : Contains the
+ * hashed commitments that build the tree.
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generate_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE *
+ HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH]) {
+ size_t i;
+ uint32_t node_ctr, parent_layer;
+
+ uint16_t merkle_leaf_indices[T];
+ uint16_t layer_offsets[LOG2(T) + 1];
+ uint16_t nodes_per_layer[LOG2(T) + 1];
+
+ /* Setup the tree to get offsets for the computation of PARENT/CHILD nodes, as well as the number of nodes per layer */
+ /* Move leafs in correct positions of the unbalanced Merkle tree */
+ setup_tree(layer_offsets, nodes_per_layer);
+ get_leaf_indices(merkle_leaf_indices, layer_offsets);
+
+ /* Place commitments on the leaves indicated by merkle_leaf_indices */
+ for (i = 0; i < T; i++) {
+ memcpy(merkle_tree + merkle_leaf_indices[i]*HASH_DIGEST_LENGTH,
+ commitments + i,
+ HASH_DIGEST_LENGTH);
+ }
+
+ /* enqueue the calls to hash */
+ int to_hash = 0;
+ int out_pos_queue[4] = {0};
+ int in_pos_queue[4] = {0};
+
+ /* create the hash tree starting from the leaves */
+ node_ctr = 0;
+ parent_layer = LOG2(T) - 1;
+ for (i = NUM_NODES_MERKLE_TREE - 1; i > 0; i -= 2) {
+ /* save the position of the hash inputs and outputs */
+ to_hash++;
+ out_pos_queue[to_hash - 1] = OFFSET(PARENT(i) + layer_offsets[parent_layer]);
+ in_pos_queue[to_hash - 1] = OFFSET(SIBLING(i));
+ /* go up to the next tree level */
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ /* hash in batches of 4 (or less when changing tree level) */
+ if (to_hash == 4 || node_ctr == 0) {
+ par_hash(
+ to_hash,
+ merkle_tree + out_pos_queue[0],
+ merkle_tree + out_pos_queue[1],
+ merkle_tree + out_pos_queue[2],
+ merkle_tree + out_pos_queue[3],
+ merkle_tree + in_pos_queue[0],
+ merkle_tree + in_pos_queue[1],
+ merkle_tree + in_pos_queue[2],
+ merkle_tree + in_pos_queue[3],
+ 2 * HASH_DIGEST_LENGTH);
+ to_hash = 0;
+ }
+ }
+}
+
+/* PQCLEAN_CROSSRSDP128FAST_AVX2_generate_merkle_proof()
+ *
+ * uint16_t merkle_proof_indices[TREE_NODES_TO_STORE] : stores the sorted indices required for the proof.
+ * uint16_t merkle_proof_len : Actual length of the proof. Can vary depending on the challenge.
+ * const unsigned char challenge : Challenge that indicated which nodes will be recomputed by the verifier.
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generate_merkle_proof(uint16_t merkle_proof_indices[TREE_NODES_TO_STORE],
+ uint16_t *merkle_proof_len,
+ const unsigned char challenge[T]) {
+ unsigned char flag_tree[NUM_NODES_MERKLE_TREE] = {NOT_COMPUTED};
+ uint32_t node_ctr, parent_layer;
+ size_t i;
+
+ uint16_t layer_offsets[LOG2(T) + 1];
+ uint16_t nodes_per_layer[LOG2(T) + 1];
+ uint16_t merkle_leaf_indices[T];
+
+ /* Setup the tree to get offsets for the computation of PARENT/CHILD nodes, as well as the number of nodes per layer */
+ setup_tree(layer_offsets, nodes_per_layer);
+ get_leaf_indices(merkle_leaf_indices, layer_offsets);
+
+ /* Use challenges to mark nodes of path tree */
+ for (size_t j = 0; j < T; j++) {
+ if (challenge[j] == CHALLENGE_PROOF_VALUE) {
+ flag_tree[merkle_leaf_indices[j]] = COMPUTED;
+ }
+ }
+
+ /* Loop over all nodes, starting at the leaves */
+ /* If at least one sibling is marked as COMPUTED, also mark the PARENT as such */
+ /* Only add sibling of COMPUTED sibling as proof node if not both of them are marked as COMPUTED. */
+ node_ctr = 0;
+ parent_layer = LOG2(T) - 1;
+ *merkle_proof_len = 0;
+ for (i = NUM_NODES_MERKLE_TREE - 1; i > 0; i -= 2) {
+
+ flag_tree[PARENT(i) + layer_offsets[parent_layer]] = (flag_tree[i] == COMPUTED) || (flag_tree[SIBLING(i)] == COMPUTED);
+
+ /* Add left sibling only if left one was computed */
+ if ( (flag_tree[i] == COMPUTED) && (flag_tree[SIBLING(i)] == NOT_COMPUTED) ) {
+ merkle_proof_indices[(*merkle_proof_len)++] = SIBLING(i);
+ }
+
+ /* Add right sibling only right was computed */
+ if ( (flag_tree[i] == NOT_COMPUTED) && (flag_tree[SIBLING(i)] == COMPUTED) ) {
+ merkle_proof_indices[(*merkle_proof_len)++] = i;
+ }
+
+ /* Due to the unbalenced structure we got to keep track of the nodes per layer processed */
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ }
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_rebuild_merkle_tree()
+ *
+ * unsigned char merkle_tree[NUM_NODES_MERKLE_TREE*HASH_DIGEST_LENGTH] : Stores the Hashes of the recomputed Merkle tree.
+ * const unsigned char merkle_proof[TREE_NODES_TO_STORE] : Merkle proof containing the nodes required for recomputation.
+ * const unsigned char commitments[T][HASH_DIGEST_LENGTH] : Stores the commitments.
+ * const unsigned char challenge[T] : Challenge vector to indicate the computed commitments.
+ */
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_rebuild_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ const unsigned char merkle_proof[TREE_NODES_TO_STORE * HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH],
+ const unsigned char challenge[T]) {
+ uint16_t flag_tree_valid[NUM_NODES_MERKLE_TREE] = {INVALID_MERKLE_NODE};
+
+ uint16_t merkle_leaf_indices[T];
+ uint16_t layer_offsets[LOG2(T) + 1];
+ uint16_t nodes_per_layer[LOG2(T) + 1];
+
+ uint16_t ctr;
+ uint32_t node_ctr, parent_layer;
+ size_t i;
+
+ /* Move leafs in correct positions of binary merkle tree */
+ /* Setup the tree again, computing the offsets and from that, the leaf indices */
+ setup_tree(layer_offsets, nodes_per_layer);
+ get_leaf_indices(merkle_leaf_indices, layer_offsets);
+
+ /* Copy the commitments to the positions indicated by the challenge */
+ for (i = 0; i < T; i++) {
+ if (challenge[i] == CHALLENGE_PROOF_VALUE) {
+ flag_tree_valid[merkle_leaf_indices[i]] = VALID_MERKLE_NODE;
+ memcpy(merkle_tree + merkle_leaf_indices[i]*HASH_DIGEST_LENGTH, commitments + i, HASH_DIGEST_LENGTH);
+ }
+ }
+
+ /* enqueue the calls to hash */
+ int to_hash = 0;
+ int out_pos_queue[4] = {0};
+ int in_pos_queue[4] = {0};
+
+ /* Create hash tree by hashing valid leaf nodes */
+ ctr = 0;
+ node_ctr = 0;
+ parent_layer = LOG2(T) - 1;
+ for (i = NUM_NODES_MERKLE_TREE - 1; i > 0; i -= 2) {
+
+ /* Both siblings are unused, but it must be kept track of the node and layer counter to chose the right offsets */
+ if (flag_tree_valid[i] == INVALID_MERKLE_NODE && flag_tree_valid[SIBLING(i)] == INVALID_MERKLE_NODE) {
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ }
+
+ else {
+ /* at least one of the siblings is valid: there is a hash to compute */
+ to_hash++;
+ /* save the position of the hash inputs and outputs */
+ out_pos_queue[to_hash - 1] = OFFSET(PARENT(i) + layer_offsets[parent_layer]);
+ in_pos_queue[to_hash - 1] = OFFSET(SIBLING(i));
+
+ /* if the right sibling is invalid, copy it from the merkle proof */
+ if (flag_tree_valid[i] == INVALID_MERKLE_NODE) {
+ memcpy(
+ merkle_tree + OFFSET(i),
+ merkle_proof + OFFSET(ctr),
+ HASH_DIGEST_LENGTH);
+ ctr++;
+ }
+
+ /* if the left sibling is invalid, copy it from the merkle proof */
+ if (flag_tree_valid[SIBLING(i)] == INVALID_MERKLE_NODE) {
+ memcpy(
+ merkle_tree + OFFSET(SIBLING(i)),
+ merkle_proof + OFFSET(ctr),
+ HASH_DIGEST_LENGTH);
+ ctr++;
+ }
+
+ /* set the parent node as valid */
+ flag_tree_valid[PARENT(i) + layer_offsets[parent_layer]] = VALID_MERKLE_NODE;
+
+ /* go up to the next tree level */
+ if (node_ctr >= (uint32_t) nodes_per_layer[parent_layer + 1] - 2) {
+ parent_layer--;
+ node_ctr = 0;
+ } else {
+ node_ctr += 2;
+ }
+ }
+
+ /* hash in batches of 4 (or less when changing tree level) */
+ if (to_hash == 4 || node_ctr == 0) {
+ par_hash(
+ to_hash,
+ merkle_tree + out_pos_queue[0],
+ merkle_tree + out_pos_queue[1],
+ merkle_tree + out_pos_queue[2],
+ merkle_tree + out_pos_queue[3],
+ merkle_tree + in_pos_queue[0],
+ merkle_tree + in_pos_queue[1],
+ merkle_tree + in_pos_queue[2],
+ merkle_tree + in_pos_queue[3],
+ 2 * HASH_DIGEST_LENGTH);
+ to_hash = 0;
+ }
+ }
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/merkle.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/merkle.h
new file mode 100644
index 000000000..3c4d87135
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/merkle.h
@@ -0,0 +1,41 @@
+/*
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (May 2023)
+ *
+ * @author: Patrick Karl
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "csprng_hash.h"
+#include "parameters.h"
+
+/***********************************************************************************************/
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generate_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH]);
+
+/***********************************************************************************************/
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generate_merkle_proof(uint16_t merkle_proof_indices[TREE_NODES_TO_STORE],
+ uint16_t *merkle_proof_len,
+ const unsigned char challenge[T]);
+
+/***********************************************************************************************/
+void PQCLEAN_CROSSRSDP128FAST_AVX2_rebuild_merkle_tree(unsigned char merkle_tree[NUM_NODES_MERKLE_TREE * HASH_DIGEST_LENGTH],
+ const unsigned char merkle_proof[TREE_NODES_TO_STORE * HASH_DIGEST_LENGTH],
+ unsigned char commitments[T][HASH_DIGEST_LENGTH],
+ const unsigned char challenge[T]);
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/merkle_tree.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/merkle_tree.h
new file mode 100644
index 000000000..2bc0a06df
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/merkle_tree.h
@@ -0,0 +1,97 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author: Patrick Karl
+ * @author Gerardo Pelosi
+ *
+ * Authors listed in lexicographic order.
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "csprng_hash.h"
+
+#define TO_PUBLISH 1
+#define NOT_TO_PUBLISH 0
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_merkle_tree_root_compute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t leaves[T][HASH_DIGEST_LENGTH]);
+uint16_t PQCLEAN_CROSSRSDP128FAST_AVX2_merkle_tree_proof_compute(uint8_t mtp[W * HASH_DIGEST_LENGTH],
+ uint8_t leaves[T][HASH_DIGEST_LENGTH],
+ const uint8_t leaves_to_reveal[T]);
+void PQCLEAN_CROSSRSDP128FAST_AVX2_merkle_tree_root_recompute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t recomputed_leaves[T][HASH_DIGEST_LENGTH],
+ const uint8_t mtp[W * HASH_DIGEST_LENGTH],
+ const uint8_t leaves_to_reveal[T]);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_merkle_tree_root_compute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t leaves[T][HASH_DIGEST_LENGTH]) {
+ uint8_t quad_hash[4][HASH_DIGEST_LENGTH];
+ int remainders[4] = {0};
+ if (T % 4 > 0) {
+ remainders[0] = 1;
+ }
+ if (T % 4 > 1) {
+ remainders[1] = 1;
+ }
+ if (T % 4 > 2) {
+ remainders[2] = 1;
+ }
+ int offset = 0;
+ for (int i = 0; i < 4; i++) {
+ hash(quad_hash[i],
+ leaves[(T / 4)*i + offset],
+ (T / 4 + remainders[i])*HASH_DIGEST_LENGTH);
+ offset += remainders[i];
+ }
+ hash(root, (const unsigned char *)quad_hash, 4 * HASH_DIGEST_LENGTH);
+}
+
+uint16_t PQCLEAN_CROSSRSDP128FAST_AVX2_merkle_tree_proof_compute(uint8_t mtp[W * HASH_DIGEST_LENGTH],
+ uint8_t leaves[T][HASH_DIGEST_LENGTH],
+ const uint8_t leaves_to_reveal[T]) {
+ uint16_t published = 0;
+ for (int i = 0; i < T; i++) {
+ if (leaves_to_reveal[i] == TO_PUBLISH) {
+ memcpy(&mtp[HASH_DIGEST_LENGTH * published],
+ &leaves[i],
+ HASH_DIGEST_LENGTH);
+ published++;
+ }
+ }
+ return published;
+}
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_merkle_tree_root_recompute(uint8_t root[HASH_DIGEST_LENGTH],
+ uint8_t recomputed_leaves[T][HASH_DIGEST_LENGTH],
+ const uint8_t mtp[W * HASH_DIGEST_LENGTH],
+ const uint8_t leaves_to_reveal[T]) {
+ uint16_t published = 0;
+ for (int i = 0; i < T; i++) {
+ if (leaves_to_reveal[i] == TO_PUBLISH) {
+ memcpy(&recomputed_leaves[i],
+ &mtp[HASH_DIGEST_LENGTH * published],
+ HASH_DIGEST_LENGTH);
+ published++;
+ }
+ }
+ PQCLEAN_CROSSRSDP128FAST_AVX2_merkle_tree_root_compute(root, recomputed_leaves);
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/pack_unpack.c b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/pack_unpack.c
new file mode 100644
index 000000000..f61e4a12a
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/pack_unpack.c
@@ -0,0 +1,618 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Jonas Schupp
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include
+#include
+
+#include "pack_unpack.h"
+
+/*Implementation of packing of 1 to 16 bits value vectors in 8 bit vectors,
+ * generic inputs from 1 to 16 bit possible*/
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_vec()
+ *
+ * uint8_t out[DENSELY_PACKED_FQ_VEC_SIZE] : FQ packed in bytes
+ * const FQ_ELEM in[N] : FQ Vec input, to be packed
+ *
+ * This function handles the packing of FQ
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_vec(uint8_t out[DENSELY_PACKED_FQ_VEC_SIZE],
+ const FQ_ELEM in[N]) {
+ PQCLEAN_CROSSRSDP128FAST_AVX2_generic_pack_fq(out, in, DENSELY_PACKED_FQ_VEC_SIZE, N);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_syn()
+ *
+ * uint8_t out[DENSELY_PACKED_FQ_SYN_SIZE] : FQ packed in bytes
+ * const FQ_ELEM in[N-K] : FQ Vec input, to be packed
+ *
+ * This function handles the packing of FQ
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_syn(uint8_t out[DENSELY_PACKED_FQ_SYN_SIZE],
+ const FQ_ELEM in[N - K]) {
+ PQCLEAN_CROSSRSDP128FAST_AVX2_generic_pack_fq(out, in, DENSELY_PACKED_FQ_SYN_SIZE, N - K);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fz_vec()
+ *
+ * uint8_t out[DENSELY_PACKED_FZ_VEC_SIZE] : FQ packed in bytes
+ * const FZ_ELEM in[N] : FQ Vec input, to be packed
+ *
+ * This function handles the packing of FQ
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fz_vec(uint8_t out[DENSELY_PACKED_FZ_VEC_SIZE],
+ const FZ_ELEM in[N]) {
+ PQCLEAN_CROSSRSDP128FAST_AVX2_generic_pack_fz(out, in, DENSELY_PACKED_FZ_VEC_SIZE, N);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fz_rsdp_g_vec()
+ *
+ * uint8_t out[DENSELY_PACKED_FZ_RSDP_G_VEC_SIZE] : Zz packed in bytes
+ * const FZ_ELEM in[M] : Zz Vec input, to be packed
+ *
+ * This function handles the packing of the add. rdsp(g) vector in Zz
+ */
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_generic_pack_fq()
+ *
+ * uint8_t *out : FQ packed in bytes
+ * const FQ_ELEM *in : FQ Vec input, to be packed
+ * size_t outlen : Length of out
+ * size_t in : Length of in
+ *
+ * This function handles the packing of an vector of el. in FQ of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_pack_fq(uint8_t *out, const FQ_ELEM *in,
+ const size_t outlen, const size_t inlen) {
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen / 8; i++) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] |= (in[i * 8 + 4] << 5) | (in[i * 8 + 5] >> 2);
+ out[i * 7 + 5] |= (in[i * 8 + 5] << 6) | (in[i * 8 + 6] >> 1);
+ out[i * 7 + 6] |= (in[i * 8 + 6] << 7) | (in[i * 8 + 7]);
+ }
+ const uint8_t n_remainder = inlen % 8;
+ if (n_remainder == 1) {
+ out[i * 7] = (in[i * 8] << 1);
+ } else if (n_remainder == 2) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] = (in[i * 8 + 1] << 2);
+ } else if (n_remainder == 3) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] = (in[i * 8 + 2] << 3);
+ } else if (n_remainder == 4) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4);
+ } else if (n_remainder == 5) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] = (in[i * 8 + 4] << 5);
+ } else if (n_remainder == 6) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] |= (in[i * 8 + 4] << 5) | (in[i * 8 + 5] >> 2);
+ out[i * 7 + 5] = (in[i * 8 + 5] << 6);
+ } else if (n_remainder == 7) {
+ out[i * 7] |= (in[i * 8] << 1) | (in[i * 8 + 1] >> 6);
+ out[i * 7 + 1] |= (in[i * 8 + 1] << 2) | (in[i * 8 + 2] >> 5);
+ out[i * 7 + 2] |= (in[i * 8 + 2] << 3) | (in[i * 8 + 3] >> 4);
+ out[i * 7 + 3] |= (in[i * 8 + 3] << 4) | (in[i * 8 + 4] >> 3);
+ out[i * 7 + 4] |= (in[i * 8 + 4] << 5) | (in[i * 8 + 5] >> 2);
+ out[i * 7 + 5] |= (in[i * 8 + 5] << 6) | (in[i * 8 + 6] >> 1);
+ out[i * 7 + 6] |= (in[i * 8 + 6] << 7);
+ }
+
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_generic_pack_fz()
+ *
+ * uint8_t *out : Zz packed in bytes
+ * const FZ_ELEM *in : Zz Vec input, to be packed
+ * size_t outlen : Length of out
+ * size_t in : Length of in
+ *
+ * This function handles the packing of an vector of el. in Zz of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_pack_fz(uint8_t *out, const FZ_ELEM *in, const size_t outlen, const size_t inlen) {
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen / 8; i++) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ out[i * 3 + 1] |= (in[i * 8 + 5] >> 2);
+ out[i * 3 + 2] = (in[i * 8 + 5] << 6);
+ out[i * 3 + 2] |= (in[i * 8 + 6] << 3);
+ out[i * 3 + 2] |= (in[i * 8 + 7]);
+ }
+ const uint8_t n_remainder = inlen % 8;
+ if (n_remainder == 1) {
+ out[i * 3] = (in[i * 8] << 5);
+ } else if (n_remainder == 2) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ } else if (n_remainder == 3) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ } else if (n_remainder == 4) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ } else if (n_remainder == 5) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ } else if (n_remainder == 6) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ out[i * 3 + 1] |= (in[i * 8 + 5] >> 2);
+ out[i * 3 + 2] = (in[i * 8 + 5] << 6);
+ } else if (n_remainder == 7) {
+ out[i * 3] = (in[i * 8] << 5);
+ out[i * 3] |= (in[i * 8 + 1] << 2);
+ out[i * 3] |= (in[i * 8 + 2] >> 1);
+ out[i * 3 + 1] = (in[i * 8 + 2] << 7);
+ out[i * 3 + 1] |= (in[i * 8 + 3] << 4);
+ out[i * 3 + 1] |= (in[i * 8 + 4] << 1);
+ out[i * 3 + 1] |= (in[i * 8 + 5] >> 2);
+ out[i * 3 + 2] = (in[i * 8 + 5] << 6);
+ out[i * 3 + 2] |= (in[i * 8 + 6] << 3);
+ }
+
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fq_vec()
+ *
+ * FQ_ELEM out[N] : FQ Vec output
+ * const uint8_t in[DENSELY_PACKED_FQ_VEC_SIZE] : FQ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fq_vec(FQ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FQ_VEC_SIZE]) {
+ PQCLEAN_CROSSRSDP128FAST_AVX2_generic_unpack_fq(out, in, N, DENSELY_PACKED_FQ_VEC_SIZE);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fq_syn()
+ *
+ * FQ_ELEM out[N] : FQ Vec output
+ * const uint8_t in[DENSELY_PACKED_FQ_SYN_SIZE] : FQ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fq_syn(FQ_ELEM out[N - K],
+ const uint8_t in[DENSELY_PACKED_FQ_SYN_SIZE]) {
+ PQCLEAN_CROSSRSDP128FAST_AVX2_generic_unpack_fq(out, in, N - K, DENSELY_PACKED_FQ_SYN_SIZE);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fz_vec()
+ *
+ * FZ_ELEM out[N] : FQ Vec output
+ * const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE] : FQ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fz_vec(FZ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE]) {
+ PQCLEAN_CROSSRSDP128FAST_AVX2_generic_unpack_fz(out, in, N);
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fz_rsdp_g_vec()
+ *
+ * FZ_ELEM out[M] : FZ Vec output
+ * const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE] : FZ Byte input, to be unpckd
+ *
+ * This function handles the unpacking of FQ
+ */
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_generic_unpack_fq()
+ *
+ * FQ_ELEM *out : FQ output, unpacked
+ * const uint8_t *in : FQ Vec input, packed in bytes
+ * size_t outlen : Length of out
+ * size_t in : Length of in
+ *
+ * This function unpacks an vector of el. in FQ of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_unpack_fq(FQ_ELEM *out, const uint8_t *in,
+ size_t outlen, size_t inlen) {
+
+ /* PQClean-edit: unused parameter */
+ (void)inlen;
+
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen / 8; i++) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ out[i * 8 + 5] = ((in[i * 7 + 4] << 2) & 0x7F);
+ out[i * 8 + 5] |= (in[i * 7 + 5] >> 6);
+ out[i * 8 + 6] = ((in[i * 7 + 5] << 1) & 0x7F);
+ out[i * 8 + 6] |= (in[i * 7 + 6] >> 7);
+ out[i * 8 + 7] = (in[i * 7 + 6] & 0x7F);
+ }
+ const uint8_t n_remainder = outlen % 8;
+ if (n_remainder == 1) {
+ out[i * 8] = (in[i * 7] >> 1);
+ } else if (n_remainder == 2) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ } else if (n_remainder == 3) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ } else if (n_remainder == 4) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ } else if (n_remainder == 5) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ } else if (n_remainder == 6) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ out[i * 8 + 5] = ((in[i * 7 + 4] << 2) & 0x7F);
+ out[i * 8 + 5] |= (in[i * 7 + 5] >> 6);
+ } else if (n_remainder == 7) {
+ out[i * 8] = (in[i * 7] >> 1);
+ out[i * 8 + 1] = ((in[i * 7] << 6) & 0x7F);
+ out[i * 8 + 1] |= (in[i * 7 + 1] >> 2);
+ out[i * 8 + 2] = ((in[i * 7 + 1] << 5) & 0x7F);
+ out[i * 8 + 2] |= (in[i * 7 + 2] >> 3);
+ out[i * 8 + 3] = ((in[i * 7 + 2] << 4) & 0x7F);
+ out[i * 8 + 3] |= (in[i * 7 + 3] >> 4);
+ out[i * 8 + 4] = ((in[i * 7 + 3] << 3) & 0x7F);
+ out[i * 8 + 4] |= (in[i * 7 + 4] >> 5);
+ out[i * 8 + 5] = ((in[i * 7 + 4] << 2) & 0x7F);
+ out[i * 8 + 5] |= (in[i * 7 + 5] >> 6);
+ out[i * 8 + 6] = ((in[i * 7 + 5] << 1) & 0x7F);
+ out[i * 8 + 6] |= (in[i * 7 + 6] >> 7);
+ }
+}
+
+/*
+ * PQCLEAN_CROSSRSDP128FAST_AVX2_generic_unpack_fz()
+ *
+ * FZ_ELEM *out : Zz output, unpacked
+ * const uint8_t *in : Zz Vec input, packed in bytes
+ * size_t outlen : Length of out
+ *
+ * This function unpacks an vector of el. in Zz of arbit. length
+ */
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_unpack_fz(FZ_ELEM *out, const uint8_t *in,
+ size_t outlen) {
+
+ size_t i;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen / 8; i++) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ out[i * 8 + 5] = ((in[i * 3 + 1] << 2) & 0x7);
+ out[i * 8 + 5] |= ((in[i * 3 + 2] >> 6) & 0x7);
+ out[i * 8 + 6] = ((in[i * 3 + 2] >> 3) & 0x7);
+ out[i * 8 + 7] = ((in[i * 3 + 2]) & 0x7);
+ }
+ const uint8_t n_remainder = outlen % 8;
+ if (n_remainder == 1) {
+ out[i * 8] = (in[i * 3] >> 5);
+ }
+ if (n_remainder == 2) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ }
+ if (n_remainder == 3) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ }
+ if (n_remainder == 4) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ }
+ if (n_remainder == 5) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ }
+ if (n_remainder == 6) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ out[i * 8 + 5] = ((in[i * 3 + 1] << 2) & 0x7);
+ out[i * 8 + 5] |= ((in[i * 3 + 2] >> 6) & 0x7);
+ }
+ if (n_remainder == 7) {
+ out[i * 8] = (in[i * 3] >> 5);
+ out[i * 8 + 1] = ((in[i * 3] >> 2) & 0x7);
+ out[i * 8 + 2] = ((in[i * 3] << 1) & 0x7);
+ out[i * 8 + 2] |= ((in[i * 3 + 1] >> 7) & 0x7);
+ out[i * 8 + 3] = ((in[i * 3 + 1] >> 4) & 0x7);
+ out[i * 8 + 4] = ((in[i * 3 + 1] >> 1) & 0x7);
+ out[i * 8 + 5] = ((in[i * 3 + 1] << 2) & 0x7);
+ out[i * 8 + 5] |= ((in[i * 3 + 2] >> 6) & 0x7);
+ out[i * 8 + 6] = ((in[i * 3 + 2] >> 3) & 0x7);
+ }
+
+}
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_uint16_t_pack(uint8_t *out, const uint16_t *in,
+ size_t outlen, size_t inlen, uint8_t btr) {
+ size_t i;
+ size_t in_i = 0;
+ uint8_t left, right;
+ uint8_t skip = 0;
+ if (btr <= 8) {
+ left = 8 - btr;
+ right = 0;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen; i++) {
+ while (right < 8 && in_i < inlen) {
+ out[i] |= (in[in_i] << (left)) >> right;
+ right += 8 - left;
+ left = 8 - btr;
+ in_i++;
+ }
+ if (right != 8) {
+ in_i--;
+ left = 2 * 8 - right;
+ } else {
+ left = 8 - btr;
+ }
+ right = 0;
+ }
+ } else if (btr == 8) {
+ for (i = 0; i < outlen; i++) {
+ out[i] = in[i];
+ }
+ } else if ((btr > 8) && (btr <= 16)) {
+ left = 0;
+ right = btr - 8;
+ skip = 0;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < outlen; i++) {
+ skip = 0;
+ while (skip == 0 && in_i < inlen) {
+ out[i] |= (uint8_t)((in[in_i] << left) >> right);
+ // First case: left == 0,
+ // i.e.: the current value covers the LSBs of the packed value
+ if (left == 0) {
+ skip = 1;
+ //Case 0: This value was complete,
+ //i.e. a new one needs to be started
+ if (right == 0) {
+ in_i++;
+ left = 0;
+ right = btr - 8;
+ }
+ //Case 1: These were not the LSBs of this value,
+ //i.e. its LSBs need to be stored in the next block
+ else if (right <= 8) {
+ left = 8 - right;
+ right = 0;
+ } else {
+ right -= 8;
+ }
+
+ }
+ // Second case: right == 0 and left > 0,
+ // i.e.: the current value is complete its LSBs
+ // are stored in the upper bits
+ else if (right == 0 && left > 0) {
+
+ right = btr - left;
+ left = 0;
+ in_i++;
+
+ }
+ }
+ }
+ }
+ /* PQClean-edit: unused parameter */
+ (void)skip;
+}
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_uint16_t_unpack(uint16_t *out, const uint8_t *in,
+ size_t outlen, size_t inlen, uint8_t btr) {
+ size_t i;
+ uint8_t skip = 0;
+ uint8_t right, left;
+ size_t out_i;
+ if (btr <= 8) {
+ out_i = 0;
+ right = 8 - btr;
+ left = 0;
+ uint8_t mask = (1 << (btr)) - 1;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen; i++) {
+ skip = 0;
+ while (skip == 0 && out_i < outlen) {
+ out[out_i] |= (((in[i] >> (right)) << left) & mask);
+ //Case 1: right > 0, i.e. the current word is done
+ //and there is a new one waiting in the same input
+ if (right > 0) {
+ out_i++;
+ if (right >= btr) {
+ right -= btr;
+ } else {
+ left = btr - right;
+ right = 0;
+ }
+ }
+ //Case 2: right == 0 and left > BITS_TO_REPRESENT(Q-1),
+ //i.e. the current word continues in the next input
+ else if (right == 0) {
+ skip = 1;
+ right = 8 - left;
+ left = 0;
+ if (right == 0) {
+ right = 8 - btr;
+ }
+ }
+ }
+ }
+ } else if (btr == 8) {
+ for (i = 0; i < outlen; i++) {
+ out[i] = in[i];
+ }
+ } else if ((btr > 8) && (btr <= 16)) {
+ left = btr - 8;
+ right = 0;
+ out_i = 0;
+ skip = 0;
+ uint16_t mask = (1 << (btr)) - 1;
+ for (i = 0; i < outlen; i++) {
+ out[i] = 0;
+ }
+ for (i = 0; i < inlen; i++) {
+ skip = 0;
+ while (skip == 0 && out_i < outlen) {
+ // Shift some value of packed poly to correct position
+ // and OR it to the target value
+ out[out_i] |= ((((uint16_t)in[i] << left) >> right) & mask);
+ // First case: the value was incomplete,
+ // i.e. the LSBs are in the next block
+ // This means that left > 0 and right == 0.
+ if (left > 0 && right == 0) {
+ // Right shift of next element for remaining bits
+ if (left <= 8) {
+ right = 8 - left;
+ left = 0;
+ } else {
+ right = 0;
+ left -= 8;
+ }
+ skip = 1;
+ }
+ // Second case: the value was complete, i.e. the LSBs are now stored
+ else if (left == 0) {
+ if (right == 0) {
+ skip = 1;
+ left = btr - 8;
+ } else {
+ left = btr - right;
+ }
+ right = 0;
+ out_i++;
+ }
+ if (left == (btr)) {
+ left = 1;
+ }
+ }
+ }
+ }
+ /* PQClean-edit: unused parameter */
+ (void)skip;
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/pack_unpack.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/pack_unpack.h
new file mode 100644
index 000000000..daaf46af8
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/pack_unpack.h
@@ -0,0 +1,70 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ * @author Jonas Schupp
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include
+#include
+
+#include "parameters.h"
+
+/* compact Z_z/F_q vector encoding functions */
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_vec(uint8_t out[DENSELY_PACKED_FQ_VEC_SIZE],
+ const FQ_ELEM in[N]);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fq_syn(uint8_t out[DENSELY_PACKED_FQ_SYN_SIZE],
+ const FQ_ELEM in[N - K]);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_pack_fz_vec(uint8_t out[DENSELY_PACKED_FZ_VEC_SIZE],
+ const FZ_ELEM in[N]);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_pack_fq(uint8_t *out, const FQ_ELEM *in,
+ size_t outlen, size_t inlen);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_pack_fz(uint8_t *out, const FZ_ELEM *in,
+ size_t outlen, size_t inlen);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fq_vec(FQ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FQ_VEC_SIZE]);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fq_syn(FQ_ELEM out[N - K],
+ const uint8_t in[DENSELY_PACKED_FQ_SYN_SIZE]);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_unpack_fz_vec(FZ_ELEM out[N],
+ const uint8_t in[DENSELY_PACKED_FZ_VEC_SIZE]);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_unpack_fq(FQ_ELEM *out, const uint8_t *in,
+ size_t outlen, size_t inlen);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_unpack_fz(FZ_ELEM *out, const uint8_t *in,
+ size_t outlen);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_uint16_t_unpack(uint16_t *out, const uint8_t *in,
+ size_t outlen, size_t inlen, uint8_t btr);
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_generic_uint16_t_pack(uint8_t *out, const uint16_t *in,
+ size_t outlen, size_t inlen, uint8_t btr);
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/parameters.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/parameters.h
new file mode 100644
index 000000000..42c4ccbb1
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/parameters.h
@@ -0,0 +1,131 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+#include
+
+#include "set.h"
+
+/******************************************************************************/
+/*************************** Base Fields Parameters ***************************/
+/******************************************************************************/
+
+/* The same base field and restriction are employed for all categories of RSDP */
+#define Q (127)
+#define Z ( 7)
+/* single-register table representation of E, the value of g^7=1 is also
+ * represented to avoid exponent renormalization*/
+#define RESTR_G_TABLE ((uint64_t) (0x0140201008040201))
+#define RESTR_G_GEN 2
+#define FQ_ELEM uint8_t
+#define FZ_ELEM uint8_t
+#define FQ_DOUBLEPREC uint16_t
+#define FQ_TRIPLEPREC uint32_t
+
+/******************************************************************************/
+/****************************** RSDP Parameters *******************************/
+/******************************************************************************/
+/********************************* Category 1 *********************************/
+#define SEC_MARGIN_LAMBDA (128)
+#define N (127)
+#define K ( 76)
+
+#define T (163)
+#define W ( 85)
+#define POSITION_IN_FW_STRING_T uint16_t
+
+/********************************* Category 3 *********************************/
+
+/******************************************************************************/
+/****************************** RSDP(G) Parameters ****************************/
+/******************************************************************************/
+
+#define HASH_CSPRNG_DOMAIN_SEP_CONST ((uint16_t)32768)
+
+/************* Helper macros for derived parameter computation ***************/
+
+#define ROUND_UP(amount, round_amt) ( (((amount)+(round_amt)-1)/(round_amt))*(round_amt) )
+
+#define IS_REPRESENTABLE_IN_D_BITS(D, N) \
+(((uint32_t) (N)>=(1UL << ((D)-1)) && (uint32_t) (N)<(1UL << (D))) ? (D) : -1)
+
+#define BITS_TO_REPRESENT(N) \
+ ((N) == 0 ? 1 : (15 \
+ + IS_REPRESENTABLE_IN_D_BITS( 1, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 2, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 3, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 4, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 5, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 6, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 7, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 8, N) \
+ + IS_REPRESENTABLE_IN_D_BITS( 9, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(10, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(11, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(12, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(13, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(14, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(15, N) \
+ + IS_REPRESENTABLE_IN_D_BITS(16, N) \
+ ) \
+ )
+
+#define LOG2(L) ( (BITS_TO_REPRESENT(L) > BITS_TO_REPRESENT((L)-1)) ? (BITS_TO_REPRESENT((L)-1)) : (BITS_TO_REPRESENT(L)) )
+
+/***************** Derived parameters *****************************************/
+#define SEED_LENGTH_BYTES (SEC_MARGIN_LAMBDA/8)
+#define KEYPAIR_SEED_LENGTH_BYTES (2*(SEC_MARGIN_LAMBDA/8))
+#define HASH_DIGEST_LENGTH (2*(SEC_MARGIN_LAMBDA/8))
+#define SALT_LENGTH_BYTES (2*(SEC_MARGIN_LAMBDA/8))
+
+#define NUM_LEAVES_MERKLE_TREE (T)
+#define NUM_NODES_MERKLE_TREE (2*NUM_LEAVES_MERKLE_TREE-1)
+
+/*to be derived via script for each T/W*/
+#define NUM_LEAVES_SEED_TREE ( T )
+// #define NUM_NODES_SEED_TREE ( 2*NUM_LEAVES_SEED_TREE-1 )
+#define NUM_INNER_NODES_SEED_TREE ( NUM_NODES_SEED_TREE-NUM_LEAVES_SEED_TREE )
+
+/* Sizes of bitpacked field element vectors
+ * Bitpacking an n-elements vector of num_bits_for_q-1 bits long values
+ * will pack 8 values in num_bits_for_q-1 bytes exactly, leaving the remaining
+ * N % 8 as a tail */
+#define DENSELY_PACKED_FQ_VEC_SIZE ((N/8)*BITS_TO_REPRESENT(Q-1) + \
+ ROUND_UP( ((N%8)*BITS_TO_REPRESENT(Q-1)),8)/8)
+#define DENSELY_PACKED_FQ_SYN_SIZE (((N-K)/8)*BITS_TO_REPRESENT(Q-1) + \
+ ROUND_UP( (((N-K)%8)*BITS_TO_REPRESENT(Q-1)),8)/8)
+#define DENSELY_PACKED_FZ_VEC_SIZE ((N/8)*BITS_TO_REPRESENT(Z-1) + \
+ ROUND_UP( ((N%8)*BITS_TO_REPRESENT(Z-1)),8)/8)
+
+/* Derived parameters computed via compute_derived_parameters.py */
+#define TREE_NODES_TO_STORE 83
+#define NUM_NODES_SEED_TREE 330
+#define NODES_PER_LEVEL_ARRAY {1, 2, 3, 6, 11, 21, 41, 82, 163}
+#define MISSING_NODES_BEFORE_LEVEL_ARRAY {0, 0, 0, 1, 3, 8, 19, 42, 88}
+#define BITS_N_ZQ_CT_RNG 923
+#define BITS_BETA_ZQSTAR_CT_RNG 1187
+#define BITS_V_CT_RNG 27260
+#define BITS_N_ZZ_CT_RNG 493
+#define BITS_CWSTR_RNG 1355
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/restr_arith.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/restr_arith.h
new file mode 100644
index 000000000..a0824b738
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/restr_arith.h
@@ -0,0 +1,77 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "parameters.h"
+
+#define FZRED_SINGLE(x) (((x) & 0x07) + ((x) >> 3))
+#define FZRED_OPPOSITE(x) ((x) ^ 0x07)
+#define FZ_DOUBLE_ZERO_NORM(x) (((x) + (((x) + 1) >> 3)) & 0x07)
+
+static inline
+void fz_dz_norm_sigma(FZ_ELEM v[N]) {
+ for (int i = 0; i < N; i++) {
+ v[i] = FZ_DOUBLE_ZERO_NORM(v[i]);
+ }
+}
+
+/* Elements of the restricted subgroups are represented as the exponents of
+ * the generator */
+static inline
+void restr_vec_sub(FZ_ELEM res[N],
+ const FZ_ELEM a[N],
+ const FZ_ELEM b[N]) {
+ for (int i = 0; i < N; i++) {
+ res[i] = FZRED_SINGLE( a[i] + FZRED_OPPOSITE(b[i]) );
+ }
+}
+
+/* Given the choice of q and z, all elements of G are represented as n-elements
+ * vectors having powers-of-two in {1,2,...,64}.
+ * Employ a round of K&R-HW.
+ * Vectorized comb based HW is also employable, testing a word against
+ * 0x01...01
+ * note that 0x80 is not excluded as sigmas are in double-zero redundant repr.
+ */
+static inline
+int is_fq_vec_in_restr_group(const FQ_ELEM in[N]) {
+ int is_in_ok = 1;
+ for (int i = 0; i < N; i++) {
+ FQ_ELEM tmp;
+ tmp = ( in[i] - (FQ_ELEM)1 ) & in[i];
+ is_in_ok = is_in_ok && (tmp == 0);
+ }
+ return is_in_ok;
+}
+
+static inline
+int is_zz_vec_in_restr_group(const FZ_ELEM in[N]) {
+ int is_in_ok = 1;
+ for (int i = 0; i < N; i++) {
+ is_in_ok = is_in_ok && (in[i] < Z);
+ }
+ return is_in_ok;
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/seedtree.c b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/seedtree.c
new file mode 100644
index 000000000..988fb17b2
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/seedtree.c
@@ -0,0 +1,134 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include "seedtree.h"
+#include
+#include // memcpy(...), memset(...)
+
+#define LEFT_CHILD(i) (2*(i)+1)
+#define RIGHT_CHILD(i) (2*(i)+2)
+#define PARENT(i) (((i)-1)/2)
+
+/* Seed tree implementation. The binary seed tree is linearized into an array
+ * from root to leaves, and from left to right. The nodes are numbered picking
+ * the indexes from the corresponding full tree, having 2**LOG2(T) leaves */
+#define DIV_BY_TWO_CEIL(i) ((i)/2 + (i) % 2)
+
+#define TO_PUBLISH 1
+#define NOT_TO_PUBLISH 0
+
+/* maximum number of parallel executions of the CSPRNG */
+#define PAR_DEGREE 4
+
+/* PQClean-edit: avoid VLA */
+#define CSPRNG_INPUT_LEN (SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + SIZEOF_UINT16)
+//const uint32_t csprng_input_len = SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + sizeof(uint16_t);
+
+int PQCLEAN_CROSSRSDP128FAST_AVX2_compute_round_seeds(unsigned char rounds_seeds[T * SEED_LENGTH_BYTES],
+ const unsigned char root_seed[SEED_LENGTH_BYTES],
+ const unsigned char salt[SALT_LENGTH_BYTES]) {
+
+ PAR_CSPRNG_STATE_T par_csprng_state;
+ CSPRNG_STATE_T single_csprng_state;
+
+ unsigned char csprng_inputs[4][CSPRNG_INPUT_LEN];
+ unsigned char csprng_outputs[4][(T / 4 + 1)*SEED_LENGTH_BYTES];
+
+ /* prepare the input buffer for the CSPRNG as the concatenation of:
+ * root_seed || salt || domain_separation_counter */
+ memcpy(csprng_inputs[0], root_seed, SEED_LENGTH_BYTES);
+ memcpy(csprng_inputs[0] + SEED_LENGTH_BYTES, salt, SALT_LENGTH_BYTES);
+ /* set counter for domain separation to 1 */
+ csprng_inputs[0][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES] = 0;
+ csprng_inputs[0][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + 1] = 1;
+
+ /* call the CSPRNG once to generate 4 seeds */
+ unsigned char quad_seed[4 * SEED_LENGTH_BYTES];
+ initialize_csprng(&single_csprng_state, csprng_inputs[0], CSPRNG_INPUT_LEN);
+ csprng_randombytes(quad_seed, 4 * SEED_LENGTH_BYTES, &single_csprng_state);
+ csprng_release(&single_csprng_state);
+
+ /* from the 4 seeds generale all T leaves */
+ for (int i = 0; i < 4; i++) {
+ memcpy(csprng_inputs[i], &quad_seed[i * SEED_LENGTH_BYTES], SEED_LENGTH_BYTES);
+ memcpy(csprng_inputs[i] + SEED_LENGTH_BYTES, salt, SALT_LENGTH_BYTES);
+ /* increment the domain separation counter */
+ csprng_inputs[i][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES] = 0;
+ csprng_inputs[i][SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + 1] = i + 2;
+ }
+ par_initialize_csprng(4, &par_csprng_state, csprng_inputs[0], csprng_inputs[1], csprng_inputs[2], csprng_inputs[3], CSPRNG_INPUT_LEN);
+ par_csprng_randombytes(4, &par_csprng_state, csprng_outputs[0], csprng_outputs[1], csprng_outputs[2], csprng_outputs[3], (T / 4 + 1)*SEED_LENGTH_BYTES);
+ par_csprng_release(4, &par_csprng_state);
+
+ int remainders[4] = {0};
+ if (T % 4 > 0) {
+ remainders[0] = 1;
+ }
+ if (T % 4 > 1) {
+ remainders[1] = 1;
+ }
+ if (T % 4 > 2) {
+ remainders[2] = 1;
+ }
+
+ int offset = 0;
+ for (int i = 0; i < 4; i++) {
+ memcpy(&rounds_seeds[((T / 4)*i + offset)*SEED_LENGTH_BYTES], csprng_outputs[i], (T / 4 + remainders[i])*SEED_LENGTH_BYTES );
+ offset += remainders[i];
+ }
+
+ return T;
+}
+
+int PQCLEAN_CROSSRSDP128FAST_AVX2_publish_round_seeds(unsigned char *seed_storage,
+ const unsigned char rounds_seeds[T * SEED_LENGTH_BYTES],
+ const unsigned char indices_to_publish[T]) {
+ int published = 0;
+ for (int i = 0; i < T; i++) {
+ if (indices_to_publish[i] == TO_PUBLISH) {
+ memcpy(&seed_storage[SEED_LENGTH_BYTES * published],
+ &rounds_seeds[i * SEED_LENGTH_BYTES],
+ SEED_LENGTH_BYTES);
+ published++;
+ }
+ }
+ return published;
+}
+
+/* simply picks seeds out of the storage and places them in the in-memory array */
+int PQCLEAN_CROSSRSDP128FAST_AVX2_regenerate_round_seeds(unsigned char rounds_seeds[T * SEED_LENGTH_BYTES],
+ const unsigned char indices_to_publish[T],
+ const unsigned char *seed_storage) {
+ int published = 0;
+ for (int i = 0; i < T; i++) {
+ if (indices_to_publish[i] == TO_PUBLISH) {
+ memcpy(&rounds_seeds[i * SEED_LENGTH_BYTES],
+ &seed_storage[SEED_LENGTH_BYTES * published],
+ SEED_LENGTH_BYTES);
+ published++;
+ }
+ }
+ return published;
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/seedtree.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/seedtree.h
new file mode 100644
index 000000000..3301b739f
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/seedtree.h
@@ -0,0 +1,44 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "csprng_hash.h"
+#include "parameters.h"
+
+void PQCLEAN_CROSSRSDP128FAST_AVX2_pseed(unsigned char seed[SEED_LENGTH_BYTES]);
+void PQCLEAN_CROSSRSDP128FAST_AVX2_ptree(unsigned char seed_tree[NUM_NODES_SEED_TREE * SEED_LENGTH_BYTES]);
+
+int PQCLEAN_CROSSRSDP128FAST_AVX2_compute_round_seeds(unsigned char rounds_seeds[T * SEED_LENGTH_BYTES],
+ const unsigned char root_seed[SEED_LENGTH_BYTES],
+ const unsigned char salt[SALT_LENGTH_BYTES]);
+
+int PQCLEAN_CROSSRSDP128FAST_AVX2_publish_round_seeds(unsigned char *seed_storage,
+ const unsigned char rounds_seeds[T * SEED_LENGTH_BYTES],
+ const unsigned char indices_to_publish[T]);
+
+int PQCLEAN_CROSSRSDP128FAST_AVX2_regenerate_round_seeds(unsigned char rounds_seeds[T * SEED_LENGTH_BYTES],
+ const unsigned char indices_to_publish[T],
+ const unsigned char *seed_storage);
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/set.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/set.h
new file mode 100644
index 000000000..0881f5c42
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/set.h
@@ -0,0 +1,25 @@
+
+#define RSDP 1
+#define CATEGORY_1 1
+#define SPEED 1
+
+#define NO_TREES 1
+
+/* liboqs-edit: when compiling avx2 just assume that Intel Instrinsics are available */
+#define IMPLEMENTATION_avx2
+#define HIGH_COMPATIBILITY_X86_64
+#define HIGH_PERFORMANCE_X86_64
+
+/* PQClean-edit: avoid VLA (don't call sizeof() when creating arrays) */
+#define SIZEOF_UINT16 2
+
+/* Undefine unused macros to facilitate dead code removal using unifdef */
+#undef SHA_3_LIBKECCAK
+/* Variant */
+#undef RSDPG
+/* Category */
+#undef CATEGORY_3
+#undef CATEGORY_5
+/* Target */
+#undef BALANCED
+#undef SIG_SIZE
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/sha3.h b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/sha3.h
new file mode 100644
index 000000000..5045aaeeb
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/sha3.h
@@ -0,0 +1,146 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#pragma once
+
+#include "fips202.h"
+/* standalone FIPS-202 implementation has
+ * different states for SHAKE depending on security level*/
+#define SHAKE_STATE_STRUCT shake128incctx
+// %%%%%%%%%%%%%%%%%% Self-contained SHAKE x1 Wrappers %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+static inline
+void xof_shake_init(SHAKE_STATE_STRUCT *state, int val) {
+ /* PQClean-edit: unused parameter */
+ (void)val;
+ shake128_inc_init(state);
+}
+
+static inline
+void xof_shake_update(SHAKE_STATE_STRUCT *state,
+ const unsigned char *input,
+ uint32_t inputByteLen) {
+ shake128_inc_absorb(state,
+ (const uint8_t *)input,
+ inputByteLen);
+}
+
+static inline
+void xof_shake_final(SHAKE_STATE_STRUCT *state) {
+ shake128_inc_finalize(state);
+}
+
+static inline
+void xof_shake_extract(SHAKE_STATE_STRUCT *state,
+ unsigned char *output,
+ uint32_t outputByteLen) {
+ shake128_inc_squeeze(output, outputByteLen, state);
+}
+
+/* PQClean-edit: CSPRNG release context */
+static inline
+void xof_shake_release(SHAKE_STATE_STRUCT *state) {
+ shake128_inc_ctx_release(state);
+}
+
+// %%%%%%%%%%%%%%%%%% Self-contained SHAKE x4 Wrappers %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#include "fips202x4.h"
+#define SHAKE_X4_STATE_STRUCT shake128x4incctx
+#define SHAKE_X4_INIT shake128x4_inc_init
+#define SHAKE_X4_ABSORB shake128x4_inc_absorb
+#define SHAKE_X4_FINALIZE shake128x4_inc_finalize
+#define SHAKE_X4_SQUEEZE shake128x4_inc_squeeze
+#define SHAKE_X4_RELEASE shake128x4_inc_ctx_release
+
+static inline void xof_shake_x4_init(SHAKE_X4_STATE_STRUCT *states) {
+ SHAKE_X4_INIT(states);
+}
+static inline void xof_shake_x4_update(SHAKE_X4_STATE_STRUCT *states,
+ const unsigned char *in1,
+ const unsigned char *in2,
+ const unsigned char *in3,
+ const unsigned char *in4,
+ uint32_t singleInputByteLen) {
+ SHAKE_X4_ABSORB(states, in1, in2, in3, in4, singleInputByteLen);
+}
+static inline void xof_shake_x4_final(SHAKE_X4_STATE_STRUCT *states) {
+ SHAKE_X4_FINALIZE(states);
+}
+static inline void xof_shake_x4_extract(SHAKE_X4_STATE_STRUCT *states,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3,
+ unsigned char *out4,
+ uint32_t singleOutputByteLen) {
+ SHAKE_X4_SQUEEZE(out1, out2, out3, out4, singleOutputByteLen, states);
+}
+static inline void xof_shake_x4_release(SHAKE_X4_STATE_STRUCT *states) {
+ SHAKE_X4_RELEASE(states);
+}
+
+// %%%%%%%%%%%%%%%%%% Self-contained SHAKE x2 Wrappers %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+/* SHAKE_x2 just calls SHAKE_x1 twice. If a suitable SHAKE_x2 implementation becomes available, it should be used instead */
+
+typedef struct {
+ SHAKE_STATE_STRUCT state1;
+ SHAKE_STATE_STRUCT state2;
+} shake_x2_ctx;
+#define SHAKE_X2_STATE_STRUCT shake_x2_ctx
+static inline void xof_shake_x2_init(SHAKE_X2_STATE_STRUCT *states) {
+ xof_shake_init(&(states->state1), 0);
+ xof_shake_init(&(states->state2), 0);
+}
+static inline void xof_shake_x2_update(SHAKE_X2_STATE_STRUCT *states,
+ const unsigned char *in1,
+ const unsigned char *in2,
+ uint32_t singleInputByteLen) {
+ xof_shake_update(&(states->state1), (const uint8_t *)in1, singleInputByteLen);
+ xof_shake_update(&(states->state2), (const uint8_t *)in2, singleInputByteLen);
+}
+static inline void xof_shake_x2_final(SHAKE_X2_STATE_STRUCT *states) {
+ xof_shake_final(&(states->state1));
+ xof_shake_final(&(states->state2));
+}
+static inline void xof_shake_x2_extract(SHAKE_X2_STATE_STRUCT *states,
+ unsigned char *out1,
+ unsigned char *out2,
+ uint32_t singleOutputByteLen) {
+ xof_shake_extract(&(states->state1), out1, singleOutputByteLen);
+ xof_shake_extract(&(states->state2), out2, singleOutputByteLen);
+}
+static inline void xof_shake_x2_release(SHAKE_X2_STATE_STRUCT *states) {
+ xof_shake_release(&(states->state1));
+ xof_shake_release(&(states->state2));
+}
+
+// %%%%%%%%%%%%%%%%%%%% Parallel SHAKE State Struct %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+typedef struct {
+ SHAKE_STATE_STRUCT state1;
+ SHAKE_X2_STATE_STRUCT state2;
+ SHAKE_X4_STATE_STRUCT state4;
+} par_shake_ctx;
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/sign.c b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/sign.c
new file mode 100644
index 000000000..a66847244
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_avx2/sign.c
@@ -0,0 +1,122 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include "api.h"
+#include "CROSS.h"
+#include "parameters.h"
+#include // size_t
+#include // memcpy
+/*----------------------------------------------------------------------------*/
+
+int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_keypair(unsigned char *pk,
+ unsigned char *sk) {
+ /* keygen cannot fail */
+ PQCLEAN_CROSSRSDP128FAST_AVX2_CROSS_keygen((prikey_t *) sk,
+ (pubkey_t *) pk);
+
+ return 0; // NIST convention: 0 == zero errors
+} // end PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_keypair
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*... generating a signed message sm[0],sm[1],...,sm[*smlen-1] */
+/*... from original message m[0],m[1],...,m[mlen-1] */
+/*... under secret key sk[0],sk[1],... */
+int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign(unsigned char *sm,
+ size_t *smlen, // out parameter
+ const unsigned char *m, size_t mlen, // in parameter
+ const unsigned char *sk) { // in parameter
+ /* sign cannot fail */
+ memcpy(sm, m, mlen);
+ PQCLEAN_CROSSRSDP128FAST_AVX2_CROSS_sign((const prikey_t *) sk, // in parameter
+ (const char *const) m, (const size_t) mlen, // in parameter
+ (CROSS_sig_t *) (sm + mlen)); // out parameter
+ *smlen = mlen + (size_t) sizeof(CROSS_sig_t);
+
+ return 0; // NIST convention: 0 == zero errors
+} // end PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*. ... verifying a signed message sm[0],sm[1],...,sm[smlen-1] */
+/*. ... under public key pk[0],pk[1],... */
+/*. ... and producing original message m[0],m[1],...,m[*mlen-1] */
+int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_open(unsigned char *m,
+ size_t *mlen, // out parameter
+ const unsigned char *sm, size_t smlen, // in parameter
+ const unsigned char *pk) { // in parameter
+
+ /* verify returns 1 if signature is ok, 0 otherwise */
+ *mlen = smlen - (size_t) sizeof(CROSS_sig_t);
+
+ memcpy((unsigned char *) m, (const unsigned char *) sm, (size_t) *mlen);
+ int ok = PQCLEAN_CROSSRSDP128FAST_AVX2_CROSS_verify((const pubkey_t *const)
+ pk, // in parameter
+ (const char *const) m, (const size_t) * mlen, // in parameter
+ (const CROSS_sig_t *const) (sm + *mlen)); // in parameter
+
+ return ok - 1; // NIST convention: 0 == zero errors, -1 == error condition
+} // end PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_open
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*... generating a signature sig[0],sig[1],...,sig[*siglen-1] */
+/*... from original message m[0],m[1],...,m[mlen-1] */
+/*... under secret key sk[0],sk[1],... */
+int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_signature(unsigned char *sig, size_t *siglen, // out parameter
+ const unsigned char *m, size_t mlen, // in parameter
+ const unsigned char *sk // in parameter
+ ) {
+ /* sign cannot fail */
+ PQCLEAN_CROSSRSDP128FAST_AVX2_CROSS_sign((const prikey_t *) sk, // in parameter
+ (const char *const) m, (const size_t) mlen, // in parameter
+ (CROSS_sig_t *) sig); // out parameter
+ *siglen = (size_t) sizeof(CROSS_sig_t);
+
+ return 0; // NIST convention: 0 == zero errors
+} // end PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_signature
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*. ... verifying a signature sig[0],sig[1],...,sig[siglen-1] */
+/*. ... under public key pk[0],pk[1],... */
+/*. ... and producing original message m[0],m[1],...,m[*mlen-1] */
+int PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_verify(const unsigned char *sig, size_t siglen, // in parameter
+ const unsigned char *m, size_t mlen, // in parameter
+ const unsigned char *pk // in parameter
+ ) {
+
+ /* PQClean-edit: unused parameter */
+ (void)siglen;
+
+ /* verify returns 1 if signature is ok, 0 otherwise */
+ int ok = PQCLEAN_CROSSRSDP128FAST_AVX2_CROSS_verify((const pubkey_t *const) pk, // in parameter
+ (const char *const) m, (const size_t) mlen, // in parameter
+ (const CROSS_sig_t *const) sig); // in parameter
+
+ return ok - 1; // NIST convention: 0 == zero errors, -1 == error condition
+} // end PQCLEAN_CROSSRSDP128FAST_AVX2_crypto_sign_verify
+
+/*----------------------------------------------------------------------------*/
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_clean/CROSS.c b/src/sig/cross/upcross_cross-rsdp-128-fast_clean/CROSS.c
new file mode 100644
index 000000000..3ea218334
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_clean/CROSS.c
@@ -0,0 +1,449 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+#include
+#include
+
+#include "CROSS.h"
+#include "csprng_hash.h"
+#include "fq_arith.h"
+#include "merkle_tree.h"
+#include "pack_unpack.h"
+#include "randombytes.h"
+#include "seedtree.h"
+
+static
+void expand_public_seed(FQ_ELEM V_tr[K][N - K],
+ const uint8_t seed_pub[KEYPAIR_SEED_LENGTH_BYTES]) {
+ CSPRNG_STATE_T CSPRNG_state_mat;
+ initialize_csprng(&CSPRNG_state_mat, seed_pub, KEYPAIR_SEED_LENGTH_BYTES);
+ CSPRNG_fq_mat(V_tr, &CSPRNG_state_mat);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_mat);
+}
+
+static
+void expand_private_seed(FZ_ELEM eta[N],
+ FQ_ELEM V_tr[K][N - K],
+ const uint8_t seed[KEYPAIR_SEED_LENGTH_BYTES]) {
+ uint8_t seede_seed_pub[2][KEYPAIR_SEED_LENGTH_BYTES];
+ CSPRNG_STATE_T CSPRNG_state;
+ initialize_csprng(&CSPRNG_state, seed, KEYPAIR_SEED_LENGTH_BYTES);
+ csprng_randombytes((uint8_t *)seede_seed_pub,
+ 2 * KEYPAIR_SEED_LENGTH_BYTES,
+ &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ expand_public_seed(V_tr, seede_seed_pub[1]);
+
+ CSPRNG_STATE_T CSPRNG_state_eta;
+ initialize_csprng(&CSPRNG_state_eta, seede_seed_pub[0], KEYPAIR_SEED_LENGTH_BYTES);
+ CSPRNG_zz_vec(eta, &CSPRNG_state_eta);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_eta);
+}
+
+void PQCLEAN_CROSSRSDP128FAST_CLEAN_CROSS_keygen(prikey_t *SK,
+ pubkey_t *PK) {
+ /* generation of random material for public and private key */
+ randombytes(SK->seed, KEYPAIR_SEED_LENGTH_BYTES);
+ uint8_t seede_seed_pub[2][KEYPAIR_SEED_LENGTH_BYTES];
+
+ CSPRNG_STATE_T CSPRNG_state;
+ initialize_csprng(&CSPRNG_state, SK->seed, KEYPAIR_SEED_LENGTH_BYTES);
+ csprng_randombytes((uint8_t *)seede_seed_pub,
+ 2 * KEYPAIR_SEED_LENGTH_BYTES,
+ &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ memcpy(PK->seed_pub, seede_seed_pub[1], KEYPAIR_SEED_LENGTH_BYTES);
+
+ /* expansion of matrix/matrices */
+ FQ_ELEM V_tr[K][N - K];
+ expand_public_seed(V_tr, PK->seed_pub);
+
+ /* expansion of secret key material */
+ FZ_ELEM eta[N];
+ CSPRNG_STATE_T CSPRNG_state_eta;
+ initialize_csprng(&CSPRNG_state_eta, seede_seed_pub[0], KEYPAIR_SEED_LENGTH_BYTES);
+
+ CSPRNG_zz_vec(eta, &CSPRNG_state_eta);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state_eta);
+
+ /* compute public syndrome */
+ FQ_ELEM pub_syn[N - K];
+ restr_vec_by_fq_matrix(pub_syn, eta, V_tr);
+ fq_dz_norm_synd(pub_syn);
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_pack_fq_syn(PK->s, pub_syn);
+}
+
+/* sign cannot fail */
+void PQCLEAN_CROSSRSDP128FAST_CLEAN_CROSS_sign(const prikey_t *const SK,
+ const char *const m,
+ const size_t mlen,
+ CROSS_sig_t *const sig) {
+ /* Wipe any residual information in the sig structure allocated by the
+ * caller */
+ memset(sig, 0, sizeof(CROSS_sig_t));
+ /* Key material expansion */
+ FQ_ELEM V_tr[K][N - K];
+ FZ_ELEM eta[N];
+ expand_private_seed(eta, V_tr, SK->seed);
+
+ uint8_t root_seed[SEED_LENGTH_BYTES];
+ randombytes(root_seed, SEED_LENGTH_BYTES);
+ randombytes(sig->salt, SALT_LENGTH_BYTES);
+
+ unsigned char rounds_seeds[T * SEED_LENGTH_BYTES] = {0};
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_compute_round_seeds(rounds_seeds, root_seed, sig->salt);
+
+ FZ_ELEM eta_tilde[T][N];
+ FZ_ELEM sigma[T][N];
+ FQ_ELEM u_tilde[T][N];
+ FQ_ELEM s_tilde[N - K];
+
+ uint8_t cmt_0_i_input[DENSELY_PACKED_FQ_SYN_SIZE +
+ DENSELY_PACKED_FZ_VEC_SIZE +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ const int offset_salt = DENSELY_PACKED_FQ_SYN_SIZE + DENSELY_PACKED_FZ_VEC_SIZE;
+ const int offset_round_idx = offset_salt + SALT_LENGTH_BYTES;
+ /* cmt_0_i_input is syndrome||sigma ||salt ; place salt at the end */
+ memcpy(cmt_0_i_input + offset_salt, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t cmt_1_i_input[SEED_LENGTH_BYTES +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ /* cmt_1_i_input is concat(seed,salt,round index) */
+ memcpy(cmt_1_i_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t cmt_0[T][HASH_DIGEST_LENGTH] = {0};
+ uint8_t cmt_1[T][HASH_DIGEST_LENGTH] = {0};
+
+ CSPRNG_STATE_T CSPRNG_state;
+ for (uint16_t i = 0; i < T; i++) {
+ /* CSPRNG is fed with concat(seed,salt,round index) represented
+ * as a 2 bytes little endian unsigned integer */
+ uint8_t csprng_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ memcpy(csprng_input, rounds_seeds + SEED_LENGTH_BYTES * i, SEED_LENGTH_BYTES);
+ memcpy(csprng_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ /* i+c */
+ uint16_t domain_sep_i = i + NUM_NODES_SEED_TREE;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES] = (domain_sep_i >> 8) & 0xFF;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + 1] = domain_sep_i & 0xFF;
+
+ /* expand seed[i] into seed_e and seed_u */
+ initialize_csprng(&CSPRNG_state,
+ csprng_input,
+ SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t));
+ /* expand eta_tilde */
+ CSPRNG_zz_vec(eta_tilde[i], &CSPRNG_state);
+ restr_vec_sub(sigma[i], eta, eta_tilde[i]);
+
+ FQ_ELEM v[N];
+ convert_restr_vec_to_fq(v, sigma[i]);
+ fz_dz_norm_sigma(sigma[i]);
+ /* expand u_tilde */
+ CSPRNG_fq_vec(u_tilde[i], &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ FQ_ELEM u[N];
+ fq_vec_by_fq_vec_pointwise(u, v, u_tilde[i]);
+ fq_vec_by_fq_matrix(s_tilde, u, V_tr);
+ fq_dz_norm_synd(s_tilde);
+
+ /* cmt_0_i_input contains s-tilde || sigma_i || salt */
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_pack_fq_syn(cmt_0_i_input, s_tilde);
+
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_pack_fz_vec(cmt_0_i_input + DENSELY_PACKED_FQ_SYN_SIZE, sigma[i]);
+ /* Fixed endianness marshalling of round counter
+ * i+c+dsc */
+ uint16_t domain_sep_idx_hash = domain_sep_i + HASH_CSPRNG_DOMAIN_SEP_CONST;
+ cmt_0_i_input[offset_round_idx] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_0_i_input[offset_round_idx + 1] = domain_sep_idx_hash & 0xFF;
+
+ hash(cmt_0[i], cmt_0_i_input, sizeof(cmt_0_i_input));
+ memcpy(cmt_1_i_input,
+ rounds_seeds + SEED_LENGTH_BYTES * i,
+ SEED_LENGTH_BYTES);
+
+ cmt_1_i_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_1_i_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + 1] = domain_sep_idx_hash & 0xFF;
+ hash(cmt_1[i], cmt_1_i_input, sizeof(cmt_1_i_input));
+
+ }
+
+ /* vector containing d_0 and d_1 from spec */
+ uint8_t commit_digests[2][HASH_DIGEST_LENGTH];
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_merkle_tree_root_compute(commit_digests[0], cmt_0);
+ hash(commit_digests[1], (unsigned char *)cmt_1, sizeof(cmt_1));
+ hash(sig->digest_01,
+ (unsigned char *) commit_digests,
+ sizeof(commit_digests));
+
+ /* first challenge extraction */
+ uint8_t beta_buf[2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES];
+ /* place d_m at the beginning of the input of the hash generating d_beta*/
+ hash(beta_buf, (uint8_t *) m, mlen);
+ memcpy(beta_buf + HASH_DIGEST_LENGTH, sig->digest_01, HASH_DIGEST_LENGTH);
+ memcpy(beta_buf + 2 * HASH_DIGEST_LENGTH, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t d_beta[HASH_DIGEST_LENGTH];
+ hash(d_beta, beta_buf, 2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES);
+
+ FQ_ELEM beta[T];
+ initialize_csprng(&CSPRNG_state, d_beta, HASH_DIGEST_LENGTH);
+ CSPRNG_fq_vec_beta(beta, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ /* Computation of the first round of responses */
+ FQ_ELEM y[T][N];
+ for (int i = 0; i < T; i++) {
+ fq_vec_by_restr_vec_scaled(y[i],
+ eta_tilde[i],
+ beta[i],
+ u_tilde[i]);
+ fq_dz_norm(y[i]);
+ }
+ /* y vectors are packed before being hashed */
+ uint8_t digest_b_buf[T * DENSELY_PACKED_FQ_VEC_SIZE + HASH_DIGEST_LENGTH];
+ for (int x = 0; x < T; x++) {
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_pack_fq_vec(digest_b_buf + (x * DENSELY_PACKED_FQ_VEC_SIZE), y[x]);
+ }
+ /* Second challenge extraction */
+ memcpy(digest_b_buf + T * DENSELY_PACKED_FQ_VEC_SIZE, d_beta, HASH_DIGEST_LENGTH);
+
+ hash(sig->digest_b, digest_b_buf, sizeof(digest_b_buf));
+
+ uint8_t fixed_weight_b[T] = {0};
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_expand_digest_to_fixed_weight(fixed_weight_b, sig->digest_b);
+
+ /* Computation of the second round of responses */
+
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_merkle_tree_proof_compute(sig->mtp, cmt_0, fixed_weight_b);
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_publish_round_seeds(sig->stp, rounds_seeds, fixed_weight_b);
+
+ int published_rsps = 0;
+ for (int i = 0; i < T; i++) {
+ if (fixed_weight_b[i] == 0) {
+ /* PQClean-edit: remove assertion */
+ //assert(published_rsps < T-W);
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_pack_fq_vec(sig->rsp_0[published_rsps].y, y[i]);
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_pack_fz_vec(sig->rsp_0[published_rsps].sigma, sigma[i]);
+ memcpy(sig->rsp_1[published_rsps], cmt_1[i], HASH_DIGEST_LENGTH);
+ published_rsps++;
+ }
+ }
+}
+
+/* PQClean-edit: avoid VLA */
+#define CSPRNG_INPUT_LENGTH (SALT_LENGTH_BYTES+SEED_LENGTH_BYTES+SIZEOF_UINT16)
+//const int csprng_input_length = SALT_LENGTH_BYTES+SEED_LENGTH_BYTES+sizeof(uint16_t);
+
+/* verify returns 1 if signature is ok, 0 otherwise */
+int PQCLEAN_CROSSRSDP128FAST_CLEAN_CROSS_verify(const pubkey_t *const PK,
+ const char *const m,
+ const size_t mlen,
+ const CROSS_sig_t *const sig) {
+ CSPRNG_STATE_T CSPRNG_state;
+
+ FQ_ELEM V_tr[K][N - K];
+ expand_public_seed(V_tr, PK->seed_pub);
+
+ FQ_ELEM pub_syn[N - K];
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_unpack_fq_syn(pub_syn, PK->s);
+
+ uint8_t beta_buf[2 * HASH_DIGEST_LENGTH + SALT_LENGTH_BYTES];
+ hash(beta_buf, (uint8_t *) m, mlen);
+ memcpy(beta_buf + HASH_DIGEST_LENGTH, sig->digest_01, HASH_DIGEST_LENGTH);
+ memcpy(beta_buf + 2 * HASH_DIGEST_LENGTH, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t d_beta[HASH_DIGEST_LENGTH];
+ hash(d_beta, beta_buf, sizeof(beta_buf));
+
+ FQ_ELEM beta[T];
+ initialize_csprng(&CSPRNG_state, d_beta, HASH_DIGEST_LENGTH);
+ CSPRNG_fq_vec_beta(beta, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ uint8_t fixed_weight_b[T] = {0};
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_expand_digest_to_fixed_weight(fixed_weight_b, sig->digest_b);
+
+ uint8_t rounds_seeds[T * SEED_LENGTH_BYTES] = {0};
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_regenerate_round_seeds(rounds_seeds, fixed_weight_b, sig->stp);
+
+ uint8_t cmt_0_i_input[DENSELY_PACKED_FQ_SYN_SIZE +
+ DENSELY_PACKED_FZ_VEC_SIZE +
+ SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ const int offset_salt = DENSELY_PACKED_FQ_SYN_SIZE + DENSELY_PACKED_FZ_VEC_SIZE;
+ const int offset_round_idx = offset_salt + SALT_LENGTH_BYTES;
+ /* cmt_0_i_input is syndrome||sigma ||salt */
+ memcpy(cmt_0_i_input + offset_salt, sig->salt, SALT_LENGTH_BYTES);
+
+ /* cmt_1_i_input is concat(seed,salt,round index) */
+ uint8_t cmt_1_i_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + sizeof(uint16_t)];
+ memcpy(cmt_1_i_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+
+ uint8_t cmt_0[T][HASH_DIGEST_LENGTH] = {0};
+ uint8_t cmt_1[T][HASH_DIGEST_LENGTH] = {0};
+
+ FZ_ELEM eta_tilde[N];
+ FQ_ELEM u_tilde[N];
+
+ FQ_ELEM y_tilde[N] = {0};
+ FQ_ELEM s_tilde[N - K] = {0};
+
+ FQ_ELEM y[T][N];
+
+ int used_rsps = 0;
+ int is_signature_ok = 1;
+ for (uint16_t i = 0; i < T; i++) {
+
+ /* i+c */
+ uint16_t domain_sep_i = i + NUM_NODES_SEED_TREE;
+ /* i+c+dsc */
+ uint16_t domain_sep_idx_hash = domain_sep_i + HASH_CSPRNG_DOMAIN_SEP_CONST;
+
+ if (fixed_weight_b[i] == 1) {
+ memcpy(cmt_1_i_input,
+ rounds_seeds + SEED_LENGTH_BYTES * i,
+ SEED_LENGTH_BYTES);
+
+ cmt_1_i_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_1_i_input[SEED_LENGTH_BYTES + SALT_LENGTH_BYTES + 1] = domain_sep_idx_hash & 0xFF;
+ hash(cmt_1[i], cmt_1_i_input, sizeof(cmt_1_i_input));
+
+ /* CSPRNG is fed with concat(seed,salt,round index) represented
+ * as a 2 bytes little endian unsigned integer */
+ uint8_t csprng_input[CSPRNG_INPUT_LENGTH];
+ memcpy(csprng_input + SEED_LENGTH_BYTES, sig->salt, SALT_LENGTH_BYTES);
+ memcpy(csprng_input, rounds_seeds + SEED_LENGTH_BYTES * i, SEED_LENGTH_BYTES);
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES] = (domain_sep_i >> 8) & 0xFF;
+ csprng_input[SALT_LENGTH_BYTES + SEED_LENGTH_BYTES + 1] = domain_sep_i & 0xFF;
+
+ /* expand seed[i] into seed_e and seed_u */
+ initialize_csprng(&CSPRNG_state, csprng_input, CSPRNG_INPUT_LENGTH);
+ /* expand eta_tilde */
+ CSPRNG_zz_vec(eta_tilde, &CSPRNG_state);
+ /* expand u_tilde */
+ CSPRNG_fq_vec(u_tilde, &CSPRNG_state);
+
+ /* PQClean-edit: CSPRNG release context */
+ csprng_release(&CSPRNG_state);
+
+ fq_vec_by_restr_vec_scaled(y[i],
+ eta_tilde,
+ beta[i],
+ u_tilde);
+ fq_dz_norm(y[i]);
+ } else {
+ /* place y[i] in the buffer for later on hashing */
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_unpack_fq_vec(y[i], sig->rsp_0[used_rsps].y);
+
+ FZ_ELEM sigma_local[N];
+ /*sigma is memcpy'ed directly into cmt_0 input buffer */
+ FZ_ELEM *sigma_ptr = cmt_0_i_input + DENSELY_PACKED_FQ_SYN_SIZE;
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_unpack_fz_vec(sigma_local, sig->rsp_0[used_rsps].sigma);
+ memcpy(sigma_ptr,
+ &sig->rsp_0[used_rsps].sigma,
+ DENSELY_PACKED_FZ_VEC_SIZE);
+ is_signature_ok = is_signature_ok &&
+ is_zz_vec_in_restr_group(sigma_local);
+ memcpy(cmt_1[i], sig->rsp_1[used_rsps], HASH_DIGEST_LENGTH);
+ used_rsps++;
+
+ FQ_ELEM v[N];
+ convert_restr_vec_to_fq(v, sigma_local);
+ fq_vec_by_fq_vec_pointwise(y_tilde, v, y[i]);
+ fq_vec_by_fq_matrix(s_tilde, y_tilde, V_tr);
+ fq_dz_norm_synd(s_tilde);
+ FQ_ELEM to_compress[N - K];
+ fq_synd_minus_fq_vec_scaled(to_compress,
+ s_tilde,
+ beta[i],
+ pub_syn);
+ fq_dz_norm_synd(to_compress);
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_pack_fq_syn(cmt_0_i_input, to_compress);
+ cmt_0_i_input[offset_round_idx] = (domain_sep_idx_hash >> 8) & 0xFF;
+ cmt_0_i_input[offset_round_idx + 1] = domain_sep_idx_hash & 0xFF;
+
+ hash(cmt_0[i], cmt_0_i_input, sizeof(cmt_0_i_input));
+ }
+ } /* end for iterating on ZKID iterations */
+
+ /* PQClean-edit: remove assertion */
+ //assert(is_signature_ok);
+
+ uint8_t commit_digests[2][HASH_DIGEST_LENGTH];
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_merkle_tree_root_recompute(commit_digests[0],
+ cmt_0,
+ sig->mtp,
+ fixed_weight_b);
+ hash(commit_digests[1], (unsigned char *)cmt_1, sizeof(cmt_1));
+
+ uint8_t digest_01_recomputed[HASH_DIGEST_LENGTH];
+ hash(digest_01_recomputed,
+ (unsigned char *) commit_digests,
+ sizeof(commit_digests));
+
+ uint8_t digest_b_buf[T * DENSELY_PACKED_FQ_VEC_SIZE + HASH_DIGEST_LENGTH];
+ for (int x = 0; x < T; x++) {
+ PQCLEAN_CROSSRSDP128FAST_CLEAN_pack_fq_vec(digest_b_buf + (x * DENSELY_PACKED_FQ_VEC_SIZE), y[x]);
+ }
+ memcpy(digest_b_buf + T * DENSELY_PACKED_FQ_VEC_SIZE, d_beta, HASH_DIGEST_LENGTH);
+
+ uint8_t digest_b_recomputed[HASH_DIGEST_LENGTH];
+ hash(digest_b_recomputed, digest_b_buf, sizeof(digest_b_buf));
+
+ int does_digest_01_match = ( memcmp(digest_01_recomputed,
+ sig->digest_01,
+ HASH_DIGEST_LENGTH) == 0);
+
+ /* PQClean-edit: remove assertion */
+ //assert(does_digest_01_match);
+
+ int does_digest_b_match = ( memcmp(digest_b_recomputed,
+ sig->digest_b,
+ HASH_DIGEST_LENGTH) == 0);
+
+ /* PQClean-edit: remove assertion */
+ //assert(does_digest_b_match);
+
+ is_signature_ok = is_signature_ok &&
+ does_digest_01_match &&
+ does_digest_b_match;
+ return is_signature_ok;
+}
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_clean/CROSS.h b/src/sig/cross/upcross_cross-rsdp-128-fast_clean/CROSS.h
new file mode 100644
index 000000000..e6d7f80c5
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_clean/CROSS.h
@@ -0,0 +1,74 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+#pragma once
+
+#include
+
+#include "pack_unpack.h"
+#include "parameters.h"
+
+/* Public key: the parity check matrix is shrunk to a seed, syndrome
+ * represented in full */
+typedef struct {
+ uint8_t seed_pub[KEYPAIR_SEED_LENGTH_BYTES];
+ uint8_t s[DENSELY_PACKED_FQ_SYN_SIZE];
+} pubkey_t;
+
+/* Private key: just a single seed*/
+typedef struct {
+ uint8_t seed[KEYPAIR_SEED_LENGTH_BYTES];
+} prikey_t;
+
+typedef struct {
+ uint8_t y[DENSELY_PACKED_FQ_VEC_SIZE];
+ uint8_t sigma[DENSELY_PACKED_FZ_VEC_SIZE];
+} rsp_0_t;
+
+/* Signature: */
+typedef struct {
+ uint8_t salt[SALT_LENGTH_BYTES];
+ uint8_t digest_01[HASH_DIGEST_LENGTH];
+ uint8_t digest_b[HASH_DIGEST_LENGTH];
+ uint8_t stp[W * SEED_LENGTH_BYTES];
+ uint8_t mtp[W * HASH_DIGEST_LENGTH];
+ rsp_0_t rsp_0[T - W];
+ uint8_t rsp_1[T - W][HASH_DIGEST_LENGTH];
+} CROSS_sig_t;
+
+/* keygen cannot fail */
+void PQCLEAN_CROSSRSDP128FAST_CLEAN_CROSS_keygen(prikey_t *SK,
+ pubkey_t *PK);
+
+/* sign cannot fail */
+void PQCLEAN_CROSSRSDP128FAST_CLEAN_CROSS_sign(const prikey_t *SK,
+ const char *m,
+ size_t mlen,
+ CROSS_sig_t *sig);
+
+/* verify returns 1 if signature is ok, 0 otherwise */
+int PQCLEAN_CROSSRSDP128FAST_CLEAN_CROSS_verify(const pubkey_t *PK,
+ const char *m,
+ size_t mlen,
+ const CROSS_sig_t *sig);
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_clean/LICENSE b/src/sig/cross/upcross_cross-rsdp-128-fast_clean/LICENSE
new file mode 100644
index 000000000..0e259d42c
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_clean/LICENSE
@@ -0,0 +1,121 @@
+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/src/sig/cross/upcross_cross-rsdp-128-fast_clean/api.h b/src/sig/cross/upcross_cross-rsdp-128-fast_clean/api.h
new file mode 100644
index 000000000..40252ff01
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_clean/api.h
@@ -0,0 +1,80 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#ifndef PQCLEAN_CROSSRSDP128FAST_CLEAN_API_H
+#define PQCLEAN_CROSSRSDP128FAST_CLEAN_API_H
+
+#pragma once
+
+#include
+#include
+
+#define PQCLEAN_CROSSRSDP128FAST_CLEAN_CRYPTO_ALGNAME "cross-rsdp-128-fast"
+
+/* no. of bytes of the secret key */
+#define PQCLEAN_CROSSRSDP128FAST_CLEAN_CRYPTO_SECRETKEYBYTES 32
+
+/* no. of bytes of the public key */
+#define PQCLEAN_CROSSRSDP128FAST_CLEAN_CRYPTO_PUBLICKEYBYTES 77
+
+/* no. of bytes of overhead in a signed message */
+#define PQCLEAN_CROSSRSDP128FAST_CLEAN_CRYPTO_BYTES 19152
+
+/* required bytes of input randomness */
+#define PQCLEAN_CROSSRSDP128FAST_CLEAN_CRYPTO_RANDOMBYTES 16
+
+int PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_keypair(unsigned char *pk,
+ unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign(unsigned char *sm,
+ size_t *smlen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_open(unsigned char *m,
+ size_t *mlen,
+ const unsigned char *sm,
+ size_t smlen,
+ const unsigned char *pk
+ );
+
+int PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_signature(unsigned char *sig,
+ size_t *siglen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *sk
+ );
+
+int PQCLEAN_CROSSRSDP128FAST_CLEAN_crypto_sign_verify(const unsigned char *sig,
+ size_t siglen,
+ const unsigned char *m,
+ size_t mlen,
+ const unsigned char *pk
+ );
+
+#endif
diff --git a/src/sig/cross/upcross_cross-rsdp-128-fast_clean/csprng_hash.c b/src/sig/cross/upcross_cross-rsdp-128-fast_clean/csprng_hash.c
new file mode 100644
index 000000000..342ee105c
--- /dev/null
+++ b/src/sig/cross/upcross_cross-rsdp-128-fast_clean/csprng_hash.c
@@ -0,0 +1,82 @@
+/**
+ *
+ * Reference ISO-C11 Implementation of CROSS.
+ *
+ * @version 1.1 (March 2023)
+ *
+ * @author Alessandro Barenghi
+ * @author Gerardo Pelosi
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include