From 557dc9e51d16cadfebb1dd4c36dfa62a04e862c6 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Thu, 15 Jan 2026 23:29:59 +0100 Subject: [PATCH] Add a high-level crypto_kem API mapping to xwing --- .gitignore | 5 +- .../msvc/vs2010/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 6 ++ .../msvc/vs2012/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 6 ++ .../msvc/vs2013/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 6 ++ .../msvc/vs2015/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 6 ++ .../msvc/vs2017/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 6 ++ .../msvc/vs2019/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 6 ++ .../msvc/vs2022/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 6 ++ .../msvc/vs2026/libsodium/libsodium.vcxproj | 2 + .../libsodium/libsodium.vcxproj.filters | 6 ++ ci/appveyor/libsodium.vcxproj | 2 + ci/appveyor/libsodium.vcxproj.filters | 6 ++ src/libsodium/Makefile.am | 1 + src/libsodium/crypto_kem/crypto_kem.c | 62 ++++++++++++++++ src/libsodium/include/Makefile.am | 1 + src/libsodium/include/sodium.h | 1 + src/libsodium/include/sodium/crypto_kem.h | 70 +++++++++++++++++++ test/default/Makefile.am | 6 ++ test/default/kem.c | 70 +++++++++++++++++++ test/default/kem.exp | 4 ++ 27 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 src/libsodium/crypto_kem/crypto_kem.c create mode 100644 src/libsodium/include/sodium/crypto_kem.h create mode 100644 test/default/kem.c create mode 100644 test/default/kem.exp diff --git a/.gitignore b/.gitignore index a92ffb5c..515a043e 100644 --- a/.gitignore +++ b/.gitignore @@ -129,10 +129,11 @@ test/default/ipcrypt test/default/kdf test/default/kdf_hkdf test/default/keygen -test/default/kx -test/default/metamorphic +test/default/kem test/default/kem_mlkem768 test/default/kem_xwing +test/default/kx +test/default/metamorphic 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 1a751c7c..6ae727e1 100644 --- a/builds/msvc/vs2010/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2010/libsodium/libsodium.vcxproj @@ -190,6 +190,7 @@ + @@ -258,6 +259,7 @@ + diff --git a/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters index 23a5a26d..2020d985 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 + crypto_kem\xwing @@ -590,6 +593,9 @@ include\sodium + + include\sodium + include\sodium diff --git a/builds/msvc/vs2012/libsodium/libsodium.vcxproj b/builds/msvc/vs2012/libsodium/libsodium.vcxproj index bbf149b9..766bb7c6 100644 --- a/builds/msvc/vs2012/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2012/libsodium/libsodium.vcxproj @@ -190,6 +190,7 @@ + @@ -258,6 +259,7 @@ + diff --git a/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters index 23a5a26d..2020d985 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 + crypto_kem\xwing @@ -590,6 +593,9 @@ include\sodium + + include\sodium + include\sodium diff --git a/builds/msvc/vs2013/libsodium/libsodium.vcxproj b/builds/msvc/vs2013/libsodium/libsodium.vcxproj index 45ec1be4..1b76be9f 100644 --- a/builds/msvc/vs2013/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2013/libsodium/libsodium.vcxproj @@ -190,6 +190,7 @@ + @@ -258,6 +259,7 @@ + diff --git a/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters index 23a5a26d..2020d985 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 + crypto_kem\xwing @@ -590,6 +593,9 @@ include\sodium + + include\sodium + include\sodium diff --git a/builds/msvc/vs2015/libsodium/libsodium.vcxproj b/builds/msvc/vs2015/libsodium/libsodium.vcxproj index 395e2564..561cee2a 100644 --- a/builds/msvc/vs2015/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2015/libsodium/libsodium.vcxproj @@ -190,6 +190,7 @@ + @@ -258,6 +259,7 @@ + diff --git a/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters index 23a5a26d..2020d985 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 + crypto_kem\xwing @@ -590,6 +593,9 @@ include\sodium + + include\sodium + include\sodium diff --git a/builds/msvc/vs2017/libsodium/libsodium.vcxproj b/builds/msvc/vs2017/libsodium/libsodium.vcxproj index 0a03f3a1..803af42d 100644 --- a/builds/msvc/vs2017/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2017/libsodium/libsodium.vcxproj @@ -190,6 +190,7 @@ + @@ -258,6 +259,7 @@ + diff --git a/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters index 23a5a26d..2020d985 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 + crypto_kem\xwing @@ -590,6 +593,9 @@ include\sodium + + include\sodium + include\sodium diff --git a/builds/msvc/vs2019/libsodium/libsodium.vcxproj b/builds/msvc/vs2019/libsodium/libsodium.vcxproj index 80bfe62a..bbd712be 100644 --- a/builds/msvc/vs2019/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2019/libsodium/libsodium.vcxproj @@ -214,6 +214,7 @@ + @@ -282,6 +283,7 @@ + diff --git a/builds/msvc/vs2019/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2019/libsodium/libsodium.vcxproj.filters index 23a5a26d..2020d985 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 + crypto_kem\xwing @@ -590,6 +593,9 @@ include\sodium + + include\sodium + include\sodium diff --git a/builds/msvc/vs2022/libsodium/libsodium.vcxproj b/builds/msvc/vs2022/libsodium/libsodium.vcxproj index 725d058e..4a2f6fa1 100644 --- a/builds/msvc/vs2022/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2022/libsodium/libsodium.vcxproj @@ -214,6 +214,7 @@ + @@ -282,6 +283,7 @@ + diff --git a/builds/msvc/vs2022/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2022/libsodium/libsodium.vcxproj.filters index 23a5a26d..2020d985 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 + crypto_kem\xwing @@ -590,6 +593,9 @@ include\sodium + + include\sodium + include\sodium diff --git a/builds/msvc/vs2026/libsodium/libsodium.vcxproj b/builds/msvc/vs2026/libsodium/libsodium.vcxproj index 37ca9675..d5cf1974 100644 --- a/builds/msvc/vs2026/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2026/libsodium/libsodium.vcxproj @@ -214,6 +214,7 @@ + @@ -282,6 +283,7 @@ + diff --git a/builds/msvc/vs2026/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2026/libsodium/libsodium.vcxproj.filters index 23a5a26d..2020d985 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 + crypto_kem\xwing @@ -590,6 +593,9 @@ include\sodium + + include\sodium + include\sodium diff --git a/ci/appveyor/libsodium.vcxproj b/ci/appveyor/libsodium.vcxproj index 64459bf2..68740212 100644 --- a/ci/appveyor/libsodium.vcxproj +++ b/ci/appveyor/libsodium.vcxproj @@ -438,6 +438,7 @@ + @@ -506,6 +507,7 @@ + diff --git a/ci/appveyor/libsodium.vcxproj.filters b/ci/appveyor/libsodium.vcxproj.filters index 3bb96fb5..021d9cac 100644 --- a/ci/appveyor/libsodium.vcxproj.filters +++ b/ci/appveyor/libsodium.vcxproj.filters @@ -381,6 +381,9 @@ Source Files + + Source Files + Source Files @@ -581,6 +584,9 @@ Header Files + + Header Files + Header Files diff --git a/src/libsodium/Makefile.am b/src/libsodium/Makefile.am index 1794e1b3..84796e3c 100644 --- a/src/libsodium/Makefile.am +++ b/src/libsodium/Makefile.am @@ -59,6 +59,7 @@ libsodium_la_SOURCES = \ crypto_kdf/crypto_kdf.c \ crypto_kdf/hkdf/kdf_hkdf_sha256.c \ crypto_kdf/hkdf/kdf_hkdf_sha512.c \ + crypto_kem/crypto_kem.c \ crypto_kem/mlkem768/kem_mlkem768.c \ crypto_kem/mlkem768/ref/kem_mlkem768_ref.c \ crypto_kem/mlkem768/ref/kem_mlkem768_ref.h \ diff --git a/src/libsodium/crypto_kem/crypto_kem.c b/src/libsodium/crypto_kem/crypto_kem.c new file mode 100644 index 00000000..68a430b9 --- /dev/null +++ b/src/libsodium/crypto_kem/crypto_kem.c @@ -0,0 +1,62 @@ +#include "crypto_kem.h" + +size_t +crypto_kem_publickeybytes(void) +{ + return crypto_kem_PUBLICKEYBYTES; +} + +size_t +crypto_kem_secretkeybytes(void) +{ + return crypto_kem_SECRETKEYBYTES; +} + +size_t +crypto_kem_ciphertextbytes(void) +{ + return crypto_kem_CIPHERTEXTBYTES; +} + +size_t +crypto_kem_sharedsecretbytes(void) +{ + return crypto_kem_SHAREDSECRETBYTES; +} + +size_t +crypto_kem_seedbytes(void) +{ + return crypto_kem_SEEDBYTES; +} + +const char * +crypto_kem_primitive(void) +{ + return crypto_kem_PRIMITIVE; +} + +int +crypto_kem_seed_keypair(unsigned char *pk, unsigned char *sk, + const unsigned char *seed) +{ + return crypto_kem_xwing_seed_keypair(pk, sk, seed); +} + +int +crypto_kem_keypair(unsigned char *pk, unsigned char *sk) +{ + return crypto_kem_xwing_keypair(pk, sk); +} + +int +crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) +{ + return crypto_kem_xwing_enc(ct, ss, pk); +} + +int +crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) +{ + return crypto_kem_xwing_dec(ss, ct, sk); +} diff --git a/src/libsodium/include/Makefile.am b/src/libsodium/include/Makefile.am index ef785abe..011f9b0f 100644 --- a/src/libsodium/include/Makefile.am +++ b/src/libsodium/include/Makefile.am @@ -33,6 +33,7 @@ SODIUM_EXPORT = \ sodium/crypto_kdf_blake2b.h \ sodium/crypto_kdf_hkdf_sha256.h \ sodium/crypto_kdf_hkdf_sha512.h \ + sodium/crypto_kem.h \ sodium/crypto_kem_mlkem768.h \ sodium/crypto_kem_xwing.h \ sodium/crypto_kx.h \ diff --git a/src/libsodium/include/sodium.h b/src/libsodium/include/sodium.h index 83df3e69..4d918f5e 100644 --- a/src/libsodium/include/sodium.h +++ b/src/libsodium/include/sodium.h @@ -33,6 +33,7 @@ #include "sodium/crypto_kdf_hkdf_sha256.h" #include "sodium/crypto_kdf_hkdf_sha512.h" #include "sodium/crypto_kdf_blake2b.h" +#include "sodium/crypto_kem.h" #include "sodium/crypto_kem_mlkem768.h" #include "sodium/crypto_kem_xwing.h" #include "sodium/crypto_kx.h" diff --git a/src/libsodium/include/sodium/crypto_kem.h b/src/libsodium/include/sodium/crypto_kem.h new file mode 100644 index 00000000..ff289e87 --- /dev/null +++ b/src/libsodium/include/sodium/crypto_kem.h @@ -0,0 +1,70 @@ +#ifndef crypto_kem_H +#define crypto_kem_H + +/* + * THREAD SAFETY: crypto_kem_keypair() is thread-safe, + * provided that sodium_init() was called before. + * + * Other functions are always thread-safe. + */ + +#include + +#include "crypto_kem_xwing.h" +#include "export.h" + +#ifdef __cplusplus +# ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wlong-long" +# endif +extern "C" { +#endif + +#define crypto_kem_PUBLICKEYBYTES crypto_kem_xwing_PUBLICKEYBYTES +SODIUM_EXPORT +size_t crypto_kem_publickeybytes(void); + +#define crypto_kem_SECRETKEYBYTES crypto_kem_xwing_SECRETKEYBYTES +SODIUM_EXPORT +size_t crypto_kem_secretkeybytes(void); + +#define crypto_kem_CIPHERTEXTBYTES crypto_kem_xwing_CIPHERTEXTBYTES +SODIUM_EXPORT +size_t crypto_kem_ciphertextbytes(void); + +#define crypto_kem_SHAREDSECRETBYTES crypto_kem_xwing_SHAREDSECRETBYTES +SODIUM_EXPORT +size_t crypto_kem_sharedsecretbytes(void); + +#define crypto_kem_SEEDBYTES crypto_kem_xwing_SEEDBYTES +SODIUM_EXPORT +size_t crypto_kem_seedbytes(void); + +#define crypto_kem_PRIMITIVE "xwing" +SODIUM_EXPORT +const char *crypto_kem_primitive(void); + +SODIUM_EXPORT +int crypto_kem_seed_keypair(unsigned char *pk, unsigned char *sk, + const unsigned char *seed) + __attribute__ ((nonnull)); + +SODIUM_EXPORT +int crypto_kem_keypair(unsigned char *pk, unsigned char *sk) + __attribute__ ((nonnull)); + +SODIUM_EXPORT +int crypto_kem_enc(unsigned char *ct, unsigned char *ss, + const unsigned char *pk) + __attribute__ ((warn_unused_result)) __attribute__ ((nonnull)); + +SODIUM_EXPORT +int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, + const unsigned char *sk) + __attribute__ ((warn_unused_result)) __attribute__ ((nonnull)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/default/Makefile.am b/test/default/Makefile.am index 8307570e..5c018f3d 100644 --- a/test/default/Makefile.am +++ b/test/default/Makefile.am @@ -49,6 +49,7 @@ EXTRA_DIST = \ ipcrypt.exp \ kdf.exp \ kdf_hkdf.exp \ + kem.exp \ kem_mlkem768.exp \ kem_xwing.exp \ keygen.exp \ @@ -144,6 +145,7 @@ DISTCLEANFILES = \ ipcrypt.res \ kdf.res \ kdf_hkdf.res \ + kem.res \ kem_mlkem768.res \ kem_xwing.res \ keygen.res \ @@ -244,6 +246,7 @@ TESTS_TARGETS = \ hash_sha3512 \ ipcrypt \ kdf \ + kem \ kem_mlkem768 \ kem_xwing \ keygen \ @@ -430,6 +433,9 @@ kdf_LDADD = $(TESTS_LDADD) kdf_hkdf_SOURCE = cmptest.h kdf_hkdf.c kdf_hkdf_LDADD = $(TESTS_LDADD) +kem_SOURCE = cmptest.h kem.c +kem_LDADD = $(TESTS_LDADD) + kem_mlkem768_SOURCE = cmptest.h kem_mlkem768.c kem_mlkem768_LDADD = $(TESTS_LDADD) diff --git a/test/default/kem.c b/test/default/kem.c new file mode 100644 index 00000000..79a55eac --- /dev/null +++ b/test/default/kem.c @@ -0,0 +1,70 @@ +#define TEST_NAME "kem" +#include "cmptest.h" + +static void +tv_kem(void) +{ + unsigned char *pk; + unsigned char *sk; + unsigned char *seed; + unsigned char *ct; + unsigned char *ss_enc; + unsigned char *ss_dec; + int i; + + pk = (unsigned char *) sodium_malloc(crypto_kem_PUBLICKEYBYTES); + sk = (unsigned char *) sodium_malloc(crypto_kem_SECRETKEYBYTES); + seed = (unsigned char *) sodium_malloc(crypto_kem_SEEDBYTES); + ct = (unsigned char *) sodium_malloc(crypto_kem_CIPHERTEXTBYTES); + ss_enc = (unsigned char *) sodium_malloc(crypto_kem_SHAREDSECRETBYTES); + ss_dec = (unsigned char *) sodium_malloc(crypto_kem_SHAREDSECRETBYTES); + + printf("primitive: %s\n", crypto_kem_primitive()); + + assert(crypto_kem_publickeybytes() == crypto_kem_PUBLICKEYBYTES); + assert(crypto_kem_secretkeybytes() == crypto_kem_SECRETKEYBYTES); + assert(crypto_kem_ciphertextbytes() == crypto_kem_CIPHERTEXTBYTES); + assert(crypto_kem_sharedsecretbytes() == crypto_kem_SHAREDSECRETBYTES); + assert(crypto_kem_seedbytes() == crypto_kem_SEEDBYTES); + + printf("constants: ok\n"); + + for (i = 0; i < (int) crypto_kem_SEEDBYTES; i++) { + seed[i] = (unsigned char) i; + } + crypto_kem_seed_keypair(pk, sk, seed); + + assert(crypto_kem_enc(ct, ss_enc, pk) == 0); + assert(crypto_kem_dec(ss_dec, ct, sk) == 0); + + if (memcmp(ss_enc, ss_dec, crypto_kem_SHAREDSECRETBYTES) != 0) { + printf("ERROR: shared secrets don't match!\n"); + } else { + printf("shared secrets match: ok\n"); + } + + crypto_kem_keypair(pk, sk); + assert(crypto_kem_enc(ct, ss_enc, pk) == 0); + assert(crypto_kem_dec(ss_dec, ct, sk) == 0); + + if (memcmp(ss_enc, ss_dec, crypto_kem_SHAREDSECRETBYTES) != 0) { + printf("ERROR: shared secrets don't match (random keys)!\n"); + } else { + printf("random keypair test: ok\n"); + } + + sodium_free(ss_dec); + sodium_free(ss_enc); + sodium_free(ct); + sodium_free(seed); + sodium_free(sk); + sodium_free(pk); +} + +int +main(void) +{ + tv_kem(); + + return 0; +} diff --git a/test/default/kem.exp b/test/default/kem.exp new file mode 100644 index 00000000..b2d52334 --- /dev/null +++ b/test/default/kem.exp @@ -0,0 +1,4 @@ +primitive: xwing +constants: ok +shared secrets match: ok +random keypair test: ok