From bd6a8af3236b6895d1117d26750736f9a1321ce3 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Thu, 15 Jan 2026 23:26:59 +0100 Subject: [PATCH] Add X-Wing --- .gitignore | 1 + .../msvc/vs2010/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 9 + .../msvc/vs2012/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 9 + .../msvc/vs2013/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 9 + .../msvc/vs2015/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 9 + .../msvc/vs2017/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 9 + .../msvc/vs2019/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 9 + .../msvc/vs2022/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 9 + .../msvc/vs2026/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 9 + ci/appveyor/libsodium.vcxproj | 2 + ci/appveyor/libsodium.vcxproj.filters | 6 + src/libsodium/Makefile.am | 1 + src/libsodium/crypto_kem/xwing/kem_xwing.c | 208 +++++++++++++++++ src/libsodium/include/Makefile.am | 1 + src/libsodium/include/sodium.h | 1 + .../include/sodium/crypto_kem_xwing.h | 69 ++++++ test/default/Makefile.am | 6 + test/default/kem_xwing.c | 217 ++++++++++++++++++ test/default/kem_xwing.exp | 12 + test/symbols/all-symbols.txt | 10 + 28 files changed, 622 insertions(+) create mode 100644 src/libsodium/crypto_kem/xwing/kem_xwing.c create mode 100644 src/libsodium/include/sodium/crypto_kem_xwing.h create mode 100644 test/default/kem_xwing.c create mode 100644 test/default/kem_xwing.exp diff --git a/.gitignore b/.gitignore index b4b14f68..a92ffb5c 100644 --- a/.gitignore +++ b/.gitignore @@ -132,6 +132,7 @@ test/default/keygen test/default/kx test/default/metamorphic test/default/kem_mlkem768 +test/default/kem_xwing test/default/misuse test/default/onetimeauth test/default/onetimeauth2 diff --git a/builds/msvc/vs2010/libsodium/libsodium.vcxproj b/builds/msvc/vs2010/libsodium/libsodium.vcxproj index c6fe81c1..1a751c7c 100644 --- a/builds/msvc/vs2010/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2010/libsodium/libsodium.vcxproj @@ -190,6 +190,7 @@ + @@ -273,6 +274,7 @@ + diff --git a/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters index fd9e8f88..23a5a26d 100644 --- a/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters @@ -390,6 +390,9 @@ crypto_aead\chacha20poly1305 + + crypto_kem\xwing + crypto_kem\mlkem768 @@ -635,6 +638,9 @@ include\sodium + + include\sodium + include\sodium @@ -1069,6 +1075,9 @@ {70a10765-f8fb-3898-8514-966e48719bc4} + + {2ef7c851-6598-3be5-88be-9ac5ec867cb0} + {898b6bd5-1360-3a34-adcd-0fade7561685} diff --git a/builds/msvc/vs2012/libsodium/libsodium.vcxproj b/builds/msvc/vs2012/libsodium/libsodium.vcxproj index ccec2101..bbf149b9 100644 --- a/builds/msvc/vs2012/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2012/libsodium/libsodium.vcxproj @@ -190,6 +190,7 @@ + @@ -273,6 +274,7 @@ + diff --git a/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters index fd9e8f88..23a5a26d 100644 --- a/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters @@ -390,6 +390,9 @@ crypto_aead\chacha20poly1305 + + crypto_kem\xwing + crypto_kem\mlkem768 @@ -635,6 +638,9 @@ include\sodium + + include\sodium + include\sodium @@ -1069,6 +1075,9 @@ {70a10765-f8fb-3898-8514-966e48719bc4} + + {2ef7c851-6598-3be5-88be-9ac5ec867cb0} + {898b6bd5-1360-3a34-adcd-0fade7561685} diff --git a/builds/msvc/vs2013/libsodium/libsodium.vcxproj b/builds/msvc/vs2013/libsodium/libsodium.vcxproj index 5b4aafc8..45ec1be4 100644 --- a/builds/msvc/vs2013/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2013/libsodium/libsodium.vcxproj @@ -190,6 +190,7 @@ + @@ -273,6 +274,7 @@ + diff --git a/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters index fd9e8f88..23a5a26d 100644 --- a/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters @@ -390,6 +390,9 @@ crypto_aead\chacha20poly1305 + + crypto_kem\xwing + crypto_kem\mlkem768 @@ -635,6 +638,9 @@ include\sodium + + include\sodium + include\sodium @@ -1069,6 +1075,9 @@ {70a10765-f8fb-3898-8514-966e48719bc4} + + {2ef7c851-6598-3be5-88be-9ac5ec867cb0} + {898b6bd5-1360-3a34-adcd-0fade7561685} diff --git a/builds/msvc/vs2015/libsodium/libsodium.vcxproj b/builds/msvc/vs2015/libsodium/libsodium.vcxproj index 6a77fc52..395e2564 100644 --- a/builds/msvc/vs2015/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2015/libsodium/libsodium.vcxproj @@ -190,6 +190,7 @@ + @@ -273,6 +274,7 @@ + diff --git a/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters index fd9e8f88..23a5a26d 100644 --- a/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters @@ -390,6 +390,9 @@ crypto_aead\chacha20poly1305 + + crypto_kem\xwing + crypto_kem\mlkem768 @@ -635,6 +638,9 @@ include\sodium + + include\sodium + include\sodium @@ -1069,6 +1075,9 @@ {70a10765-f8fb-3898-8514-966e48719bc4} + + {2ef7c851-6598-3be5-88be-9ac5ec867cb0} + {898b6bd5-1360-3a34-adcd-0fade7561685} diff --git a/builds/msvc/vs2017/libsodium/libsodium.vcxproj b/builds/msvc/vs2017/libsodium/libsodium.vcxproj index 28abc9b7..0a03f3a1 100644 --- a/builds/msvc/vs2017/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2017/libsodium/libsodium.vcxproj @@ -190,6 +190,7 @@ + @@ -273,6 +274,7 @@ + diff --git a/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters index fd9e8f88..23a5a26d 100644 --- a/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters @@ -390,6 +390,9 @@ crypto_aead\chacha20poly1305 + + crypto_kem\xwing + crypto_kem\mlkem768 @@ -635,6 +638,9 @@ include\sodium + + include\sodium + include\sodium @@ -1069,6 +1075,9 @@ {70a10765-f8fb-3898-8514-966e48719bc4} + + {2ef7c851-6598-3be5-88be-9ac5ec867cb0} + {898b6bd5-1360-3a34-adcd-0fade7561685} diff --git a/builds/msvc/vs2019/libsodium/libsodium.vcxproj b/builds/msvc/vs2019/libsodium/libsodium.vcxproj index 6b1d8677..80bfe62a 100644 --- a/builds/msvc/vs2019/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2019/libsodium/libsodium.vcxproj @@ -214,6 +214,7 @@ + @@ -297,6 +298,7 @@ + diff --git a/builds/msvc/vs2019/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2019/libsodium/libsodium.vcxproj.filters index fd9e8f88..23a5a26d 100644 --- a/builds/msvc/vs2019/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2019/libsodium/libsodium.vcxproj.filters @@ -390,6 +390,9 @@ crypto_aead\chacha20poly1305 + + crypto_kem\xwing + crypto_kem\mlkem768 @@ -635,6 +638,9 @@ include\sodium + + include\sodium + include\sodium @@ -1069,6 +1075,9 @@ {70a10765-f8fb-3898-8514-966e48719bc4} + + {2ef7c851-6598-3be5-88be-9ac5ec867cb0} + {898b6bd5-1360-3a34-adcd-0fade7561685} diff --git a/builds/msvc/vs2022/libsodium/libsodium.vcxproj b/builds/msvc/vs2022/libsodium/libsodium.vcxproj index c0708797..725d058e 100644 --- a/builds/msvc/vs2022/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2022/libsodium/libsodium.vcxproj @@ -214,6 +214,7 @@ + @@ -297,6 +298,7 @@ + diff --git a/builds/msvc/vs2022/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2022/libsodium/libsodium.vcxproj.filters index fd9e8f88..23a5a26d 100644 --- a/builds/msvc/vs2022/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2022/libsodium/libsodium.vcxproj.filters @@ -390,6 +390,9 @@ crypto_aead\chacha20poly1305 + + crypto_kem\xwing + crypto_kem\mlkem768 @@ -635,6 +638,9 @@ include\sodium + + include\sodium + include\sodium @@ -1069,6 +1075,9 @@ {70a10765-f8fb-3898-8514-966e48719bc4} + + {2ef7c851-6598-3be5-88be-9ac5ec867cb0} + {898b6bd5-1360-3a34-adcd-0fade7561685} diff --git a/builds/msvc/vs2026/libsodium/libsodium.vcxproj b/builds/msvc/vs2026/libsodium/libsodium.vcxproj index fbe69650..37ca9675 100644 --- a/builds/msvc/vs2026/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2026/libsodium/libsodium.vcxproj @@ -214,6 +214,7 @@ + @@ -297,6 +298,7 @@ + diff --git a/builds/msvc/vs2026/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2026/libsodium/libsodium.vcxproj.filters index fd9e8f88..23a5a26d 100644 --- a/builds/msvc/vs2026/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2026/libsodium/libsodium.vcxproj.filters @@ -390,6 +390,9 @@ crypto_aead\chacha20poly1305 + + crypto_kem\xwing + crypto_kem\mlkem768 @@ -635,6 +638,9 @@ include\sodium + + include\sodium + include\sodium @@ -1069,6 +1075,9 @@ {70a10765-f8fb-3898-8514-966e48719bc4} + + {2ef7c851-6598-3be5-88be-9ac5ec867cb0} + {898b6bd5-1360-3a34-adcd-0fade7561685} diff --git a/ci/appveyor/libsodium.vcxproj b/ci/appveyor/libsodium.vcxproj index 9158cf38..64459bf2 100644 --- a/ci/appveyor/libsodium.vcxproj +++ b/ci/appveyor/libsodium.vcxproj @@ -438,6 +438,7 @@ + @@ -521,6 +522,7 @@ + diff --git a/ci/appveyor/libsodium.vcxproj.filters b/ci/appveyor/libsodium.vcxproj.filters index 81c1b174..3bb96fb5 100644 --- a/ci/appveyor/libsodium.vcxproj.filters +++ b/ci/appveyor/libsodium.vcxproj.filters @@ -381,6 +381,9 @@ Source Files + + Source Files + Source Files @@ -626,6 +629,9 @@ Header Files + + Header Files + Header Files diff --git a/src/libsodium/Makefile.am b/src/libsodium/Makefile.am index 1f565e48..1794e1b3 100644 --- a/src/libsodium/Makefile.am +++ b/src/libsodium/Makefile.am @@ -62,6 +62,7 @@ libsodium_la_SOURCES = \ crypto_kem/mlkem768/kem_mlkem768.c \ crypto_kem/mlkem768/ref/kem_mlkem768_ref.c \ crypto_kem/mlkem768/ref/kem_mlkem768_ref.h \ + crypto_kem/xwing/kem_xwing.c \ crypto_kx/crypto_kx.c \ crypto_onetimeauth/crypto_onetimeauth.c \ crypto_onetimeauth/poly1305/onetimeauth_poly1305.c \ diff --git a/src/libsodium/crypto_kem/xwing/kem_xwing.c b/src/libsodium/crypto_kem/xwing/kem_xwing.c new file mode 100644 index 00000000..1c965109 --- /dev/null +++ b/src/libsodium/crypto_kem/xwing/kem_xwing.c @@ -0,0 +1,208 @@ +#include +#include + +#include "crypto_hash_sha3.h" +#include "crypto_kem_mlkem768.h" +#include "crypto_kem_xwing.h" +#include "crypto_scalarmult_curve25519.h" +#include "crypto_xof_shake256.h" +#include "private/common.h" +#include "randombytes.h" +#include "utils.h" + +static const unsigned char xwing_label[6] = { 0x5c, 0x2e, 0x2f, 0x2f, 0x5e, 0x5c }; + +static void +expand_decaps_key(unsigned char pk_mlkem[crypto_kem_mlkem768_PUBLICKEYBYTES], + unsigned char sk_mlkem[crypto_kem_mlkem768_SECRETKEYBYTES], + unsigned char pk_x25519[crypto_scalarmult_curve25519_BYTES], + unsigned char sk_x25519[crypto_scalarmult_curve25519_SCALARBYTES], + const unsigned char seed[crypto_kem_xwing_SEEDBYTES]) +{ + unsigned char expanded[96]; + unsigned char mlkem_seed[crypto_kem_mlkem768_SEEDBYTES]; + + crypto_xof_shake256(expanded, 96, seed, crypto_kem_xwing_SEEDBYTES); + + memcpy(mlkem_seed, expanded, 64); + memcpy(sk_x25519, expanded + 64, 32); + + crypto_kem_mlkem768_seed_keypair(pk_mlkem, sk_mlkem, mlkem_seed); + crypto_scalarmult_curve25519_base(pk_x25519, sk_x25519); + + sodium_memzero(expanded, sizeof expanded); + sodium_memzero(mlkem_seed, sizeof mlkem_seed); +} + +static void +combiner(unsigned char ss[crypto_kem_xwing_SHAREDSECRETBYTES], + const unsigned char ss_mlkem[crypto_kem_mlkem768_SHAREDSECRETBYTES], + const unsigned char ss_x25519[crypto_scalarmult_curve25519_BYTES], + const unsigned char ct_x25519[crypto_scalarmult_curve25519_BYTES], + const unsigned char pk_x25519[crypto_scalarmult_curve25519_BYTES]) +{ + crypto_hash_sha3256_state state; + + crypto_hash_sha3256_init(&state); + crypto_hash_sha3256_update(&state, ss_mlkem, crypto_kem_mlkem768_SHAREDSECRETBYTES); + crypto_hash_sha3256_update(&state, ss_x25519, crypto_scalarmult_curve25519_BYTES); + crypto_hash_sha3256_update(&state, ct_x25519, crypto_scalarmult_curve25519_BYTES); + crypto_hash_sha3256_update(&state, pk_x25519, crypto_scalarmult_curve25519_BYTES); + crypto_hash_sha3256_update(&state, xwing_label, sizeof xwing_label); + crypto_hash_sha3256_final(&state, ss); +} + +size_t +crypto_kem_xwing_publickeybytes(void) +{ + return crypto_kem_xwing_PUBLICKEYBYTES; +} + +size_t +crypto_kem_xwing_secretkeybytes(void) +{ + return crypto_kem_xwing_SECRETKEYBYTES; +} + +size_t +crypto_kem_xwing_ciphertextbytes(void) +{ + return crypto_kem_xwing_CIPHERTEXTBYTES; +} + +size_t +crypto_kem_xwing_sharedsecretbytes(void) +{ + return crypto_kem_xwing_SHAREDSECRETBYTES; +} + +size_t +crypto_kem_xwing_seedbytes(void) +{ + return crypto_kem_xwing_SEEDBYTES; +} + +int +crypto_kem_xwing_seed_keypair(unsigned char *pk, unsigned char *sk, const unsigned char *seed) +{ + unsigned char pk_mlkem[crypto_kem_mlkem768_PUBLICKEYBYTES]; + unsigned char sk_mlkem[crypto_kem_mlkem768_SECRETKEYBYTES]; + unsigned char pk_x25519[crypto_scalarmult_curve25519_BYTES]; + unsigned char sk_x25519[crypto_scalarmult_curve25519_SCALARBYTES]; + + expand_decaps_key(pk_mlkem, sk_mlkem, pk_x25519, sk_x25519, seed); + + memcpy(pk, pk_mlkem, crypto_kem_mlkem768_PUBLICKEYBYTES); + memcpy(pk + crypto_kem_mlkem768_PUBLICKEYBYTES, pk_x25519, crypto_scalarmult_curve25519_BYTES); + + memcpy(sk, seed, crypto_kem_xwing_SEEDBYTES); + + sodium_memzero(sk_mlkem, sizeof sk_mlkem); + sodium_memzero(sk_x25519, sizeof sk_x25519); + + return 0; +} + +int +crypto_kem_xwing_keypair(unsigned char *pk, unsigned char *sk) +{ + unsigned char seed[crypto_kem_xwing_SEEDBYTES]; + + randombytes_buf(seed, crypto_kem_xwing_SEEDBYTES); + crypto_kem_xwing_seed_keypair(pk, sk, seed); + + sodium_memzero(seed, sizeof seed); + + return 0; +} + +int +crypto_kem_xwing_enc_deterministic(unsigned char *ct, unsigned char *ss, const unsigned char *pk, + const unsigned char *seed) +{ + const unsigned char *pk_mlkem = pk; + const unsigned char *pk_x25519 = pk + crypto_kem_mlkem768_PUBLICKEYBYTES; + + const unsigned char *seed_mlkem = seed; + const unsigned char *sk_e_x25519 = seed + 32; + + unsigned char ct_mlkem[crypto_kem_mlkem768_CIPHERTEXTBYTES]; + unsigned char ss_mlkem[crypto_kem_mlkem768_SHAREDSECRETBYTES]; + unsigned char ct_x25519[crypto_scalarmult_curve25519_BYTES]; + unsigned char ss_x25519[crypto_scalarmult_curve25519_BYTES]; + + if (crypto_kem_mlkem768_enc_deterministic(ct_mlkem, ss_mlkem, pk_mlkem, seed_mlkem) != 0) { + return -1; + } + + crypto_scalarmult_curve25519_base(ct_x25519, sk_e_x25519); + + if (crypto_scalarmult_curve25519(ss_x25519, sk_e_x25519, pk_x25519) != 0) { + sodium_memzero(ss_mlkem, sizeof ss_mlkem); + return -1; + } + + memcpy(ct, ct_mlkem, crypto_kem_mlkem768_CIPHERTEXTBYTES); + memcpy(ct + crypto_kem_mlkem768_CIPHERTEXTBYTES, ct_x25519, crypto_scalarmult_curve25519_BYTES); + + combiner(ss, ss_mlkem, ss_x25519, ct_x25519, pk_x25519); + + sodium_memzero(ss_mlkem, sizeof ss_mlkem); + sodium_memzero(ss_x25519, sizeof ss_x25519); + + return 0; +} + +int +crypto_kem_xwing_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) +{ + unsigned char seed[64]; + + randombytes_buf(seed, 64); + if (crypto_kem_xwing_enc_deterministic(ct, ss, pk, seed) != 0) { + sodium_memzero(seed, sizeof seed); + return -1; + } + sodium_memzero(seed, sizeof seed); + + return 0; +} + +int +crypto_kem_xwing_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) +{ + unsigned char pk_mlkem[crypto_kem_mlkem768_PUBLICKEYBYTES]; + unsigned char sk_mlkem[crypto_kem_mlkem768_SECRETKEYBYTES]; + unsigned char pk_x25519[crypto_scalarmult_curve25519_BYTES]; + unsigned char sk_x25519[crypto_scalarmult_curve25519_SCALARBYTES]; + + const unsigned char *ct_mlkem = ct; + const unsigned char *ct_x25519 = ct + crypto_kem_mlkem768_CIPHERTEXTBYTES; + + unsigned char ss_mlkem[crypto_kem_mlkem768_SHAREDSECRETBYTES]; + unsigned char ss_x25519[crypto_scalarmult_curve25519_BYTES]; + + expand_decaps_key(pk_mlkem, sk_mlkem, pk_x25519, sk_x25519, sk); + + if (crypto_kem_mlkem768_dec(ss_mlkem, ct_mlkem, sk_mlkem) != 0) { + sodium_memzero(sk_mlkem, sizeof sk_mlkem); + sodium_memzero(sk_x25519, sizeof sk_x25519); + return -1; + } + + if (crypto_scalarmult_curve25519(ss_x25519, sk_x25519, ct_x25519) != 0) { + sodium_memzero(ss_mlkem, sizeof ss_mlkem); + sodium_memzero(sk_mlkem, sizeof sk_mlkem); + sodium_memzero(sk_x25519, sizeof sk_x25519); + return -1; + } + + combiner(ss, ss_mlkem, ss_x25519, ct_x25519, pk_x25519); + + sodium_memzero(ss_mlkem, sizeof ss_mlkem); + sodium_memzero(ss_x25519, sizeof ss_x25519); + sodium_memzero(sk_mlkem, sizeof sk_mlkem); + sodium_memzero(sk_x25519, sizeof sk_x25519); + + return 0; +} diff --git a/src/libsodium/include/Makefile.am b/src/libsodium/include/Makefile.am index 693df80c..ef785abe 100644 --- a/src/libsodium/include/Makefile.am +++ b/src/libsodium/include/Makefile.am @@ -34,6 +34,7 @@ SODIUM_EXPORT = \ sodium/crypto_kdf_hkdf_sha256.h \ sodium/crypto_kdf_hkdf_sha512.h \ sodium/crypto_kem_mlkem768.h \ + sodium/crypto_kem_xwing.h \ sodium/crypto_kx.h \ sodium/crypto_onetimeauth.h \ sodium/crypto_onetimeauth_poly1305.h \ diff --git a/src/libsodium/include/sodium.h b/src/libsodium/include/sodium.h index bd27cd8c..83df3e69 100644 --- a/src/libsodium/include/sodium.h +++ b/src/libsodium/include/sodium.h @@ -34,6 +34,7 @@ #include "sodium/crypto_kdf_hkdf_sha512.h" #include "sodium/crypto_kdf_blake2b.h" #include "sodium/crypto_kem_mlkem768.h" +#include "sodium/crypto_kem_xwing.h" #include "sodium/crypto_kx.h" #include "sodium/crypto_onetimeauth.h" #include "sodium/crypto_onetimeauth_poly1305.h" diff --git a/src/libsodium/include/sodium/crypto_kem_xwing.h b/src/libsodium/include/sodium/crypto_kem_xwing.h new file mode 100644 index 00000000..d1be2d08 --- /dev/null +++ b/src/libsodium/include/sodium/crypto_kem_xwing.h @@ -0,0 +1,69 @@ +#ifndef crypto_kem_xwing_H +#define crypto_kem_xwing_H + +#include + +#include "export.h" + +#ifdef __cplusplus +# ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wlong-long" +# endif +extern "C" { +#endif + +#define crypto_kem_xwing_PUBLICKEYBYTES 1216U +SODIUM_EXPORT +size_t crypto_kem_xwing_publickeybytes(void); + +#define crypto_kem_xwing_SECRETKEYBYTES 32U +SODIUM_EXPORT +size_t crypto_kem_xwing_secretkeybytes(void); + +#define crypto_kem_xwing_CIPHERTEXTBYTES 1120U +SODIUM_EXPORT +size_t crypto_kem_xwing_ciphertextbytes(void); + +#define crypto_kem_xwing_SHAREDSECRETBYTES 32U +SODIUM_EXPORT +size_t crypto_kem_xwing_sharedsecretbytes(void); + +#define crypto_kem_xwing_SEEDBYTES 32U +SODIUM_EXPORT +size_t crypto_kem_xwing_seedbytes(void); + +SODIUM_EXPORT +int crypto_kem_xwing_seed_keypair(unsigned char pk[crypto_kem_xwing_PUBLICKEYBYTES], + unsigned char sk[crypto_kem_xwing_SECRETKEYBYTES], + const unsigned char seed[crypto_kem_xwing_SEEDBYTES]) + __attribute__((nonnull)); + +SODIUM_EXPORT +int crypto_kem_xwing_keypair(unsigned char pk[crypto_kem_xwing_PUBLICKEYBYTES], + unsigned char sk[crypto_kem_xwing_SECRETKEYBYTES]) + __attribute__((nonnull)); + +SODIUM_EXPORT +int crypto_kem_xwing_enc(unsigned char ct[crypto_kem_xwing_CIPHERTEXTBYTES], + unsigned char ss[crypto_kem_xwing_SHAREDSECRETBYTES], + const unsigned char pk[crypto_kem_xwing_PUBLICKEYBYTES]) + __attribute__((warn_unused_result)) __attribute__((nonnull)); + +SODIUM_EXPORT +int crypto_kem_xwing_enc_deterministic(unsigned char ct[crypto_kem_xwing_CIPHERTEXTBYTES], + unsigned char ss[crypto_kem_xwing_SHAREDSECRETBYTES], + const unsigned char pk[crypto_kem_xwing_PUBLICKEYBYTES], + const unsigned char seed[64]) + __attribute__((warn_unused_result)) __attribute__((nonnull)); + +SODIUM_EXPORT +int crypto_kem_xwing_dec(unsigned char ss[crypto_kem_xwing_SHAREDSECRETBYTES], + const unsigned char ct[crypto_kem_xwing_CIPHERTEXTBYTES], + const unsigned char sk[crypto_kem_xwing_SECRETKEYBYTES]) + __attribute__((warn_unused_result)) __attribute__((nonnull)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/default/Makefile.am b/test/default/Makefile.am index b8e15daf..8307570e 100644 --- a/test/default/Makefile.am +++ b/test/default/Makefile.am @@ -50,6 +50,7 @@ EXTRA_DIST = \ kdf.exp \ kdf_hkdf.exp \ kem_mlkem768.exp \ + kem_xwing.exp \ keygen.exp \ kx.exp \ metamorphic.exp \ @@ -144,6 +145,7 @@ DISTCLEANFILES = \ kdf.res \ kdf_hkdf.res \ kem_mlkem768.res \ + kem_xwing.res \ keygen.res \ kx.res \ metamorphic.res \ @@ -243,6 +245,7 @@ TESTS_TARGETS = \ ipcrypt \ kdf \ kem_mlkem768 \ + kem_xwing \ keygen \ kx \ metamorphic \ @@ -430,6 +433,9 @@ kdf_hkdf_LDADD = $(TESTS_LDADD) kem_mlkem768_SOURCE = cmptest.h kem_mlkem768.c kem_mlkem768_LDADD = $(TESTS_LDADD) +kem_xwing_SOURCE = cmptest.h kem_xwing.c +kem_xwing_LDADD = $(TESTS_LDADD) + keygen_SOURCE = cmptest.h keygen.c keygen_LDADD = $(TESTS_LDADD) diff --git a/test/default/kem_xwing.c b/test/default/kem_xwing.c new file mode 100644 index 00000000..c008c97e --- /dev/null +++ b/test/default/kem_xwing.c @@ -0,0 +1,217 @@ +#define TEST_NAME "kem_xwing" +#include "cmptest.h" + +static const char tv0_seed[] = + "0000000000000000000000000000000000000000000000000000000000000000"; +static const char tv0_randomness[] = + "6464646464646464646464646464646464646464646464646464646464646464" + "6464646464646464646464646464646464646464646464646464646464646464"; +static const char tv0_ek_prefix[] = + "3d209f716752f6408e7f89bceef97ac388530045377927644ef046c0a7cae978"; +static const char tv0_ct_prefix[] = + "d81018a94f8078e02105beaa814e003390befa4589bb614f7739"; +static const char tv0_ss[] = + "e5ba94031ea6efd69c09c254f6d9783136ba6037e2d4c43bcccf19d6f3f4343a"; + +static const char tv1_seed[] = + "0101010101010101010101010101010101010101010101010101010101010101"; +static const char tv1_randomness[] = + "6565656565656565656565656565656565656565656565656565656565656565" + "6565656565656565656565656565656565656565656565656565656565656565"; +static const char tv1_ek_prefix[] = + "ec7b50cddc8360f98b189bac73d395ef947b37d8453886a253269f7b18b9eb78"; +static const char tv1_ct_prefix[] = + "600ecf4026683898d0e339eeea9ebd437a4a802952bf32bfa326"; +static const char tv1_ss[] = + "750300db25bff9620e893c2c6fcab9bf04d7f2e543b5b39420485626fa274908"; + +static const char tv2_seed[] = + "0202020202020202020202020202020202020202020202020202020202020202"; +static const char tv2_randomness[] = + "6666666666666666666666666666666666666666666666666666666666666666" + "6666666666666666666666666666666666666666666666666666666666666666"; +static const char tv2_ek_prefix[] = + "08118d8819772292c976ec971ee3039195800c823544484595cc63450b9db941"; +static const char tv2_ct_prefix[] = + "413c55d5710bae6376761dada807daffd4dc45f9f70d825e0d46"; +static const char tv2_ss[] = + "87292f18b2e7af74bb8839ddee15e832d2f4bfac14dc84f824906d951436aafa"; + +static int +test_kat_vector(const char *seed_hex, const char *randomness_hex, + const char *ek_prefix_hex, const char *ct_prefix_hex, + const char *ss_hex) +{ + unsigned char seed[crypto_kem_xwing_SEEDBYTES]; + unsigned char pk[crypto_kem_xwing_PUBLICKEYBYTES]; + unsigned char sk[crypto_kem_xwing_SECRETKEYBYTES]; + unsigned char randomness[64]; + unsigned char ct[crypto_kem_xwing_CIPHERTEXTBYTES]; + unsigned char ss_enc[crypto_kem_xwing_SHAREDSECRETBYTES]; + unsigned char ss_dec[crypto_kem_xwing_SHAREDSECRETBYTES]; + unsigned char expected_ek_prefix[32]; + unsigned char expected_ct_prefix[26]; + unsigned char expected_ss[32]; + char hex[65]; + + sodium_hex2bin(seed, sizeof seed, seed_hex, strlen(seed_hex), NULL, NULL, NULL); + sodium_hex2bin(randomness, sizeof randomness, randomness_hex, strlen(randomness_hex), + NULL, NULL, NULL); + sodium_hex2bin(expected_ek_prefix, sizeof expected_ek_prefix, ek_prefix_hex, + strlen(ek_prefix_hex), NULL, NULL, NULL); + sodium_hex2bin(expected_ct_prefix, sizeof expected_ct_prefix, ct_prefix_hex, + strlen(ct_prefix_hex), NULL, NULL, NULL); + sodium_hex2bin(expected_ss, sizeof expected_ss, ss_hex, strlen(ss_hex), NULL, NULL, NULL); + + crypto_kem_xwing_seed_keypair(pk, sk, seed); + + if (memcmp(pk, expected_ek_prefix, 32) != 0) { + sodium_bin2hex(hex, sizeof hex, pk, 32); + printf("pk mismatch: got %s\n", hex); + return -1; + } + + assert(crypto_kem_xwing_enc_deterministic(ct, ss_enc, pk, randomness) == 0); + + if (memcmp(ct, expected_ct_prefix, 26) != 0) { + sodium_bin2hex(hex, sizeof hex, ct, 26); + printf("ct mismatch: got %s\n", hex); + return -1; + } + + if (memcmp(ss_enc, expected_ss, 32) != 0) { + sodium_bin2hex(hex, sizeof hex, ss_enc, 32); + printf("ss_enc mismatch: got %s\n", hex); + return -1; + } + + assert(crypto_kem_xwing_dec(ss_dec, ct, sk) == 0); + + if (memcmp(ss_dec, expected_ss, 32) != 0) { + sodium_bin2hex(hex, sizeof hex, ss_dec, 32); + printf("ss_dec mismatch: got %s\n", hex); + return -1; + } + + return 0; +} + +static void +tv_kem_xwing(void) +{ + unsigned char *pk; + unsigned char *sk; + unsigned char *seed; + unsigned char *ct; + unsigned char *ss_enc; + unsigned char *ss_dec; + unsigned char *randomness; + char hex[65]; + int i; + + pk = (unsigned char *) sodium_malloc(crypto_kem_xwing_PUBLICKEYBYTES); + sk = (unsigned char *) sodium_malloc(crypto_kem_xwing_SECRETKEYBYTES); + seed = (unsigned char *) sodium_malloc(crypto_kem_xwing_SEEDBYTES); + ct = (unsigned char *) sodium_malloc(crypto_kem_xwing_CIPHERTEXTBYTES); + ss_enc = (unsigned char *) sodium_malloc(crypto_kem_xwing_SHAREDSECRETBYTES); + ss_dec = (unsigned char *) sodium_malloc(crypto_kem_xwing_SHAREDSECRETBYTES); + randomness = (unsigned char *) sodium_malloc(64); + + for (i = 0; i < (int) crypto_kem_xwing_SEEDBYTES; i++) { + seed[i] = (unsigned char) i; + } + crypto_kem_xwing_seed_keypair(pk, sk, seed); + + sodium_bin2hex(hex, sizeof hex, pk, 32); + printf("pk (first 32 bytes): [%s]\n", hex); + sodium_bin2hex(hex, sizeof hex, sk, 32); + printf("sk: [%s]\n", hex); + + for (i = 0; i < 64; i++) { + randomness[i] = (unsigned char)(i + 64); + } + assert(crypto_kem_xwing_enc_deterministic(ct, ss_enc, pk, randomness) == 0); + + sodium_bin2hex(hex, sizeof hex, ct, 32); + printf("ct (first 32 bytes): [%s]\n", hex); + sodium_bin2hex(hex, sizeof hex, ss_enc, crypto_kem_xwing_SHAREDSECRETBYTES); + printf("ss_enc: [%s]\n", hex); + + assert(crypto_kem_xwing_dec(ss_dec, ct, sk) == 0); + + sodium_bin2hex(hex, sizeof hex, ss_dec, crypto_kem_xwing_SHAREDSECRETBYTES); + printf("ss_dec: [%s]\n", hex); + + if (memcmp(ss_enc, ss_dec, crypto_kem_xwing_SHAREDSECRETBYTES) != 0) { + printf("ERROR: shared secrets don't match!\n"); + } else { + printf("shared secrets match: ok\n"); + } + + crypto_kem_xwing_keypair(pk, sk); + assert(crypto_kem_xwing_enc(ct, ss_enc, pk) == 0); + assert(crypto_kem_xwing_dec(ss_dec, ct, sk) == 0); + if (memcmp(ss_enc, ss_dec, crypto_kem_xwing_SHAREDSECRETBYTES) != 0) { + printf("ERROR: shared secrets don't match (random keys)!\n"); + } else { + printf("random keypair test: ok\n"); + } + + assert(crypto_kem_xwing_publickeybytes() == crypto_kem_xwing_PUBLICKEYBYTES); + assert(crypto_kem_xwing_secretkeybytes() == crypto_kem_xwing_SECRETKEYBYTES); + assert(crypto_kem_xwing_ciphertextbytes() == crypto_kem_xwing_CIPHERTEXTBYTES); + assert(crypto_kem_xwing_sharedsecretbytes() == crypto_kem_xwing_SHAREDSECRETBYTES); + assert(crypto_kem_xwing_seedbytes() == crypto_kem_xwing_SEEDBYTES); + + assert(crypto_kem_xwing_PUBLICKEYBYTES == 1216U); + assert(crypto_kem_xwing_SECRETKEYBYTES == 32U); + assert(crypto_kem_xwing_CIPHERTEXTBYTES == 1120U); + assert(crypto_kem_xwing_SHAREDSECRETBYTES == 32U); + assert(crypto_kem_xwing_SEEDBYTES == 32U); + + printf("constants: ok\n"); + + sodium_free(randomness); + sodium_free(ss_dec); + sodium_free(ss_enc); + sodium_free(ct); + sodium_free(seed); + sodium_free(sk); + sodium_free(pk); + + printf("tv_kem_xwing: ok\n"); +} + +static void +tv_kem_xwing_kat(void) +{ + printf("IETF KAT vector 0: "); + if (test_kat_vector(tv0_seed, tv0_randomness, tv0_ek_prefix, tv0_ct_prefix, tv0_ss) == 0) { + printf("ok\n"); + } else { + printf("FAILED\n"); + } + + printf("IETF KAT vector 1: "); + if (test_kat_vector(tv1_seed, tv1_randomness, tv1_ek_prefix, tv1_ct_prefix, tv1_ss) == 0) { + printf("ok\n"); + } else { + printf("FAILED\n"); + } + + printf("IETF KAT vector 2: "); + if (test_kat_vector(tv2_seed, tv2_randomness, tv2_ek_prefix, tv2_ct_prefix, tv2_ss) == 0) { + printf("ok\n"); + } else { + printf("FAILED\n"); + } +} + +int +main(void) +{ + tv_kem_xwing(); + tv_kem_xwing_kat(); + + return 0; +} diff --git a/test/default/kem_xwing.exp b/test/default/kem_xwing.exp new file mode 100644 index 00000000..0f74c945 --- /dev/null +++ b/test/default/kem_xwing.exp @@ -0,0 +1,12 @@ +pk (first 32 bytes): [6f54098a0a0e641146614b6960ba60d8603d62f447f9ab499b47bd6906cc40b0] +sk: [000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f] +ct (first 32 bytes): [332c248ecac774a5b9e28b7018565b7e07b57733b8e68a432084b39b9221e497] +ss_enc: [f285b028f4de617b6adf9eccbd811327848dd44ac7078c15390b16682576ad8c] +ss_dec: [f285b028f4de617b6adf9eccbd811327848dd44ac7078c15390b16682576ad8c] +shared secrets match: ok +random keypair test: ok +constants: ok +tv_kem_xwing: ok +IETF KAT vector 0: ok +IETF KAT vector 1: ok +IETF KAT vector 2: ok diff --git a/test/symbols/all-symbols.txt b/test/symbols/all-symbols.txt index fed74188..8d1b7a2c 100644 --- a/test/symbols/all-symbols.txt +++ b/test/symbols/all-symbols.txt @@ -386,6 +386,16 @@ crypto_kem_mlkem768_secretkeybytes crypto_kem_mlkem768_seed_keypair crypto_kem_mlkem768_seedbytes crypto_kem_mlkem768_sharedsecretbytes +crypto_kem_xwing_ciphertextbytes +crypto_kem_xwing_dec +crypto_kem_xwing_enc +crypto_kem_xwing_enc_deterministic +crypto_kem_xwing_keypair +crypto_kem_xwing_publickeybytes +crypto_kem_xwing_secretkeybytes +crypto_kem_xwing_seed_keypair +crypto_kem_xwing_seedbytes +crypto_kem_xwing_sharedsecretbytes crypto_kx_client_session_keys crypto_kx_keypair crypto_kx_primitive