From bca64e0982646950f15a4f9389b1db2fafb7b2da Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Tue, 7 Apr 2026 23:00:49 +0200 Subject: [PATCH] Add ML-KEM768 --- .gitignore | 1 + src/libsodium/Makefile.am | 3 + src/libsodium/Makefile.in | 36 +- .../crypto_kem/mlkem768/kem_mlkem768.c | 63 ++ .../mlkem768/ref/kem_mlkem768_ref.c | 807 ++++++++++++++++++ .../mlkem768/ref/kem_mlkem768_ref.h | 20 + src/libsodium/include/Makefile.am | 1 + src/libsodium/include/Makefile.in | 1 + src/libsodium/include/sodium.h | 1 + .../include/sodium/crypto_kem_mlkem768.h | 70 ++ src/libsodium/include/sodium/private/quirks.h | 5 + test/default/Makefile.am | 1 + test/default/Makefile.in | 303 +++++-- test/default/kem_mlkem768.c | 365 ++++++++ test/default/kem_mlkem768.exp | 14 + 15 files changed, 1622 insertions(+), 69 deletions(-) create mode 100644 src/libsodium/crypto_kem/mlkem768/kem_mlkem768.c create mode 100644 src/libsodium/crypto_kem/mlkem768/ref/kem_mlkem768_ref.c create mode 100644 src/libsodium/crypto_kem/mlkem768/ref/kem_mlkem768_ref.h create mode 100644 src/libsodium/include/sodium/crypto_kem_mlkem768.h create mode 100644 test/default/kem_mlkem768.c create mode 100644 test/default/kem_mlkem768.exp diff --git a/.gitignore b/.gitignore index f60cda3b..0cf152c9 100644 --- a/.gitignore +++ b/.gitignore @@ -136,6 +136,7 @@ test/default/kdf_hkdf4 test/default/keygen test/default/kx test/default/metamorphic +test/default/kem_mlkem768 test/default/misuse test/default/onetimeauth test/default/onetimeauth2 diff --git a/src/libsodium/Makefile.am b/src/libsodium/Makefile.am index fc74245d..486fdbd1 100644 --- a/src/libsodium/Makefile.am +++ b/src/libsodium/Makefile.am @@ -57,6 +57,9 @@ libsodium_la_SOURCES = \ crypto_kdf/crypto_kdf.c \ crypto_kdf/hkdf/kdf_hkdf_sha256.c \ crypto_kdf/hkdf/kdf_hkdf_sha512.c \ + crypto_kem/mlkem768/kem_mlkem768.c \ + crypto_kem/mlkem768/ref/kem_mlkem768_ref.c \ + crypto_kem/mlkem768/ref/kem_mlkem768_ref.h \ crypto_kx/crypto_kx.c \ crypto_onetimeauth/crypto_onetimeauth.c \ crypto_onetimeauth/poly1305/onetimeauth_poly1305.c \ diff --git a/src/libsodium/Makefile.in b/src/libsodium/Makefile.in index 78690f03..5e47feac 100644 --- a/src/libsodium/Makefile.in +++ b/src/libsodium/Makefile.in @@ -315,8 +315,9 @@ am__libsodium_la_SOURCES_DIST = \ crypto_hash/sha256/cp/hash_sha256_cp.c \ crypto_hash/sha512/hash_sha512.c \ crypto_hash/sha512/cp/hash_sha512_cp.c \ - crypto_ipcrypt/crypto_ipcrypt.c crypto_ipcrypt/ipcrypt_soft.c \ - crypto_ipcrypt/ipcrypt_soft.h crypto_ipcrypt/implementations.h \ + crypto_hash/sha3/hash_sha3.c crypto_ipcrypt/crypto_ipcrypt.c \ + crypto_ipcrypt/ipcrypt_soft.c crypto_ipcrypt/ipcrypt_soft.h \ + crypto_ipcrypt/implementations.h \ crypto_kdf/blake2b/kdf_blake2b.c crypto_kdf/crypto_kdf.c \ crypto_kdf/hkdf/kdf_hkdf_sha256.c \ crypto_kdf/hkdf/kdf_hkdf_sha512.c crypto_kx/crypto_kx.c \ @@ -501,6 +502,7 @@ am_libsodium_la_OBJECTS = \ crypto_hash/sha256/cp/libsodium_la-hash_sha256_cp.lo \ crypto_hash/sha512/libsodium_la-hash_sha512.lo \ crypto_hash/sha512/cp/libsodium_la-hash_sha512_cp.lo \ + crypto_hash/sha3/libsodium_la-hash_sha3.lo \ crypto_ipcrypt/libsodium_la-crypto_ipcrypt.lo \ crypto_ipcrypt/libsodium_la-ipcrypt_soft.lo \ crypto_kdf/blake2b/libsodium_la-kdf_blake2b.lo \ @@ -652,6 +654,7 @@ am__depfiles_remade = crypto_aead/aegis128l/$(DEPDIR)/libaesni_la-aegis128l_aesn crypto_hash/$(DEPDIR)/libsodium_la-crypto_hash.Plo \ crypto_hash/sha256/$(DEPDIR)/libsodium_la-hash_sha256.Plo \ crypto_hash/sha256/cp/$(DEPDIR)/libsodium_la-hash_sha256_cp.Plo \ + crypto_hash/sha3/$(DEPDIR)/libsodium_la-hash_sha3.Plo \ crypto_hash/sha512/$(DEPDIR)/libsodium_la-hash_sha512.Plo \ crypto_hash/sha512/cp/$(DEPDIR)/libsodium_la-hash_sha512_cp.Plo \ crypto_ipcrypt/$(DEPDIR)/libaesni_la-ipcrypt_aesni.Plo \ @@ -1071,8 +1074,9 @@ libsodium_la_SOURCES = crypto_aead/aegis128l/aead_aegis128l.c \ crypto_hash/sha256/cp/hash_sha256_cp.c \ crypto_hash/sha512/hash_sha512.c \ crypto_hash/sha512/cp/hash_sha512_cp.c \ - crypto_ipcrypt/crypto_ipcrypt.c crypto_ipcrypt/ipcrypt_soft.c \ - crypto_ipcrypt/ipcrypt_soft.h crypto_ipcrypt/implementations.h \ + crypto_hash/sha3/hash_sha3.c crypto_ipcrypt/crypto_ipcrypt.c \ + crypto_ipcrypt/ipcrypt_soft.c crypto_ipcrypt/ipcrypt_soft.h \ + crypto_ipcrypt/implementations.h \ crypto_kdf/blake2b/kdf_blake2b.c crypto_kdf/crypto_kdf.c \ crypto_kdf/hkdf/kdf_hkdf_sha256.c \ crypto_kdf/hkdf/kdf_hkdf_sha512.c crypto_kx/crypto_kx.c \ @@ -1710,6 +1714,15 @@ crypto_hash/sha512/cp/$(DEPDIR)/$(am__dirstamp): crypto_hash/sha512/cp/libsodium_la-hash_sha512_cp.lo: \ crypto_hash/sha512/cp/$(am__dirstamp) \ crypto_hash/sha512/cp/$(DEPDIR)/$(am__dirstamp) +crypto_hash/sha3/$(am__dirstamp): + @$(MKDIR_P) crypto_hash/sha3 + @: >>crypto_hash/sha3/$(am__dirstamp) +crypto_hash/sha3/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) crypto_hash/sha3/$(DEPDIR) + @: >>crypto_hash/sha3/$(DEPDIR)/$(am__dirstamp) +crypto_hash/sha3/libsodium_la-hash_sha3.lo: \ + crypto_hash/sha3/$(am__dirstamp) \ + crypto_hash/sha3/$(DEPDIR)/$(am__dirstamp) crypto_ipcrypt/libsodium_la-crypto_ipcrypt.lo: \ crypto_ipcrypt/$(am__dirstamp) \ crypto_ipcrypt/$(DEPDIR)/$(am__dirstamp) @@ -2366,6 +2379,8 @@ mostlyclean-compile: -rm -f crypto_hash/sha256/*.lo -rm -f crypto_hash/sha256/cp/*.$(OBJEXT) -rm -f crypto_hash/sha256/cp/*.lo + -rm -f crypto_hash/sha3/*.$(OBJEXT) + -rm -f crypto_hash/sha3/*.lo -rm -f crypto_hash/sha512/*.$(OBJEXT) -rm -f crypto_hash/sha512/*.lo -rm -f crypto_hash/sha512/cp/*.$(OBJEXT) @@ -2533,6 +2548,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@crypto_hash/$(DEPDIR)/libsodium_la-crypto_hash.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@crypto_hash/sha256/$(DEPDIR)/libsodium_la-hash_sha256.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@crypto_hash/sha256/cp/$(DEPDIR)/libsodium_la-hash_sha256_cp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@crypto_hash/sha3/$(DEPDIR)/libsodium_la-hash_sha3.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@crypto_hash/sha512/$(DEPDIR)/libsodium_la-hash_sha512.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@crypto_hash/sha512/cp/$(DEPDIR)/libsodium_la-hash_sha512_cp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@crypto_ipcrypt/$(DEPDIR)/libaesni_la-ipcrypt_aesni.Plo@am__quote@ # am--include-marker @@ -3038,6 +3054,13 @@ crypto_hash/sha512/cp/libsodium_la-hash_sha512_cp.lo: crypto_hash/sha512/cp/hash @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsodium_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o crypto_hash/sha512/cp/libsodium_la-hash_sha512_cp.lo `test -f 'crypto_hash/sha512/cp/hash_sha512_cp.c' || echo '$(srcdir)/'`crypto_hash/sha512/cp/hash_sha512_cp.c +crypto_hash/sha3/libsodium_la-hash_sha3.lo: crypto_hash/sha3/hash_sha3.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsodium_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT crypto_hash/sha3/libsodium_la-hash_sha3.lo -MD -MP -MF crypto_hash/sha3/$(DEPDIR)/libsodium_la-hash_sha3.Tpo -c -o crypto_hash/sha3/libsodium_la-hash_sha3.lo `test -f 'crypto_hash/sha3/hash_sha3.c' || echo '$(srcdir)/'`crypto_hash/sha3/hash_sha3.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) crypto_hash/sha3/$(DEPDIR)/libsodium_la-hash_sha3.Tpo crypto_hash/sha3/$(DEPDIR)/libsodium_la-hash_sha3.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypto_hash/sha3/hash_sha3.c' object='crypto_hash/sha3/libsodium_la-hash_sha3.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsodium_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o crypto_hash/sha3/libsodium_la-hash_sha3.lo `test -f 'crypto_hash/sha3/hash_sha3.c' || echo '$(srcdir)/'`crypto_hash/sha3/hash_sha3.c + crypto_ipcrypt/libsodium_la-crypto_ipcrypt.lo: crypto_ipcrypt/crypto_ipcrypt.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsodium_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT crypto_ipcrypt/libsodium_la-crypto_ipcrypt.lo -MD -MP -MF crypto_ipcrypt/$(DEPDIR)/libsodium_la-crypto_ipcrypt.Tpo -c -o crypto_ipcrypt/libsodium_la-crypto_ipcrypt.lo `test -f 'crypto_ipcrypt/crypto_ipcrypt.c' || echo '$(srcdir)/'`crypto_ipcrypt/crypto_ipcrypt.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) crypto_ipcrypt/$(DEPDIR)/libsodium_la-crypto_ipcrypt.Tpo crypto_ipcrypt/$(DEPDIR)/libsodium_la-crypto_ipcrypt.Plo @@ -3682,6 +3705,7 @@ clean-libtool: -rm -rf crypto_hash/.libs crypto_hash/_libs -rm -rf crypto_hash/sha256/.libs crypto_hash/sha256/_libs -rm -rf crypto_hash/sha256/cp/.libs crypto_hash/sha256/cp/_libs + -rm -rf crypto_hash/sha3/.libs crypto_hash/sha3/_libs -rm -rf crypto_hash/sha512/.libs crypto_hash/sha512/_libs -rm -rf crypto_hash/sha512/cp/.libs crypto_hash/sha512/cp/_libs -rm -rf crypto_ipcrypt/.libs crypto_ipcrypt/_libs @@ -4015,6 +4039,8 @@ distclean-generic: -$(am__rm_f) crypto_hash/sha256/$(am__dirstamp) -$(am__rm_f) crypto_hash/sha256/cp/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) crypto_hash/sha256/cp/$(am__dirstamp) + -$(am__rm_f) crypto_hash/sha3/$(DEPDIR)/$(am__dirstamp) + -$(am__rm_f) crypto_hash/sha3/$(am__dirstamp) -$(am__rm_f) crypto_hash/sha512/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) crypto_hash/sha512/$(am__dirstamp) -$(am__rm_f) crypto_hash/sha512/cp/$(DEPDIR)/$(am__dirstamp) @@ -4188,6 +4214,7 @@ distclean: distclean-recursive -rm -f crypto_hash/$(DEPDIR)/libsodium_la-crypto_hash.Plo -rm -f crypto_hash/sha256/$(DEPDIR)/libsodium_la-hash_sha256.Plo -rm -f crypto_hash/sha256/cp/$(DEPDIR)/libsodium_la-hash_sha256_cp.Plo + -rm -f crypto_hash/sha3/$(DEPDIR)/libsodium_la-hash_sha3.Plo -rm -f crypto_hash/sha512/$(DEPDIR)/libsodium_la-hash_sha512.Plo -rm -f crypto_hash/sha512/cp/$(DEPDIR)/libsodium_la-hash_sha512_cp.Plo -rm -f crypto_ipcrypt/$(DEPDIR)/libaesni_la-ipcrypt_aesni.Plo @@ -4371,6 +4398,7 @@ maintainer-clean: maintainer-clean-recursive -rm -f crypto_hash/$(DEPDIR)/libsodium_la-crypto_hash.Plo -rm -f crypto_hash/sha256/$(DEPDIR)/libsodium_la-hash_sha256.Plo -rm -f crypto_hash/sha256/cp/$(DEPDIR)/libsodium_la-hash_sha256_cp.Plo + -rm -f crypto_hash/sha3/$(DEPDIR)/libsodium_la-hash_sha3.Plo -rm -f crypto_hash/sha512/$(DEPDIR)/libsodium_la-hash_sha512.Plo -rm -f crypto_hash/sha512/cp/$(DEPDIR)/libsodium_la-hash_sha512_cp.Plo -rm -f crypto_ipcrypt/$(DEPDIR)/libaesni_la-ipcrypt_aesni.Plo diff --git a/src/libsodium/crypto_kem/mlkem768/kem_mlkem768.c b/src/libsodium/crypto_kem/mlkem768/kem_mlkem768.c new file mode 100644 index 00000000..3bafa887 --- /dev/null +++ b/src/libsodium/crypto_kem/mlkem768/kem_mlkem768.c @@ -0,0 +1,63 @@ +#include "crypto_kem_mlkem768.h" +#include "ref/kem_mlkem768_ref.h" + +size_t +crypto_kem_mlkem768_publickeybytes(void) +{ + return crypto_kem_mlkem768_PUBLICKEYBYTES; +} + +size_t +crypto_kem_mlkem768_secretkeybytes(void) +{ + return crypto_kem_mlkem768_SECRETKEYBYTES; +} + +size_t +crypto_kem_mlkem768_ciphertextbytes(void) +{ + return crypto_kem_mlkem768_CIPHERTEXTBYTES; +} + +size_t +crypto_kem_mlkem768_sharedsecretbytes(void) +{ + return crypto_kem_mlkem768_SHAREDSECRETBYTES; +} + +size_t +crypto_kem_mlkem768_seedbytes(void) +{ + return crypto_kem_mlkem768_SEEDBYTES; +} + +int +crypto_kem_mlkem768_seed_keypair(unsigned char *pk, unsigned char *sk, const unsigned char *seed) +{ + return mlkem768_ref_seed_keypair(pk, sk, seed); +} + +int +crypto_kem_mlkem768_keypair(unsigned char *pk, unsigned char *sk) +{ + return mlkem768_ref_keypair(pk, sk); +} + +int +crypto_kem_mlkem768_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) +{ + return mlkem768_ref_enc(ct, ss, pk); +} + +int +crypto_kem_mlkem768_enc_deterministic(unsigned char *ct, unsigned char *ss, const unsigned char *pk, + const unsigned char *seed) +{ + return mlkem768_ref_enc_deterministic(ct, ss, pk, seed); +} + +int +crypto_kem_mlkem768_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) +{ + return mlkem768_ref_dec(ss, ct, sk); +} diff --git a/src/libsodium/crypto_kem/mlkem768/ref/kem_mlkem768_ref.c b/src/libsodium/crypto_kem/mlkem768/ref/kem_mlkem768_ref.c new file mode 100644 index 00000000..2b90332c --- /dev/null +++ b/src/libsodium/crypto_kem/mlkem768/ref/kem_mlkem768_ref.c @@ -0,0 +1,807 @@ +#include +#include + +#include "crypto_hash_sha3.h" +#include "crypto_kem_mlkem768.h" +#include "crypto_xof_shake128.h" +#include "crypto_xof_shake256.h" +#include "kem_mlkem768_ref.h" +#include "private/common.h" +#include "randombytes.h" +#include "utils.h" + +#define MLKEM768_Q 3329 +#define MLKEM768_N 256 +#define MLKEM768_K 3 +#define MLKEM768_ETA1 2 +#define MLKEM768_ETA2 2 +#define MLKEM768_DU 10 +#define MLKEM768_DV 4 + +#define MLKEM768_POLYBYTES 384 +#define MLKEM768_POLYVECBYTES (MLKEM768_K * MLKEM768_POLYBYTES) +#define MLKEM768_POLYCOMPRESSEDBYTES_DU 320 +#define MLKEM768_POLYCOMPRESSEDBYTES_DV 128 +#define MLKEM768_POLYVECCOMPRESSEDBYTES_DU (MLKEM768_K * MLKEM768_POLYCOMPRESSEDBYTES_DU) + +typedef struct poly { + int16_t coeffs[MLKEM768_N]; +} poly; + +typedef struct polyvec { + poly vec[MLKEM768_K]; +} polyvec; + +static const int16_t zetas[128] = { + 2285, 2571, 2970, 1812, 1493, 1422, 287, 202, 3158, 622, 1577, 182, 962, 2127, 1855, 1468, + 573, 2004, 264, 383, 2500, 1458, 1727, 3199, 2648, 1017, 732, 608, 1787, 411, 3124, 1758, + 1223, 652, 2777, 1015, 2036, 1491, 3047, 1785, 516, 3321, 3009, 2663, 1711, 2167, 126, 1469, + 2476, 3239, 3058, 830, 107, 1908, 3082, 2378, 2931, 961, 1821, 2604, 448, 2264, 677, 2054, + 2226, 430, 555, 843, 2078, 871, 1550, 105, 422, 587, 177, 3094, 3038, 2869, 1574, 1653, + 3083, 778, 1159, 3182, 2552, 1483, 2727, 1119, 1739, 644, 2457, 349, 418, 329, 3173, 3254, + 817, 1097, 603, 610, 1322, 2044, 1864, 384, 2114, 3193, 1218, 1994, 2455, 220, 2142, 1670, + 2144, 1799, 2051, 794, 1819, 2475, 2459, 478, 3221, 3021, 996, 991, 958, 1869, 1522, 1628 +}; + +static int16_t +montgomery_reduce(int32_t a) +{ + int16_t t; + + t = (int16_t) ((uint16_t) a * 62209U); + t = (int16_t) ((a - (int32_t) t * MLKEM768_Q) >> 16); + + return t; +} + +static int16_t +barrett_reduce(int16_t a) +{ + int16_t t; + + t = (int16_t) (((int32_t) a * 20159) >> 26); + t = a - t * MLKEM768_Q; + + return t; +} + +static int16_t +csubq(int16_t a) +{ + a -= MLKEM768_Q; + a += (a >> 15) & MLKEM768_Q; + + return a; +} + +static void +poly_ntt(poly *r) +{ + unsigned int len, start, j, k; + int16_t t, zeta; + + k = 1; + for (len = 128; len >= 2; len >>= 1) { + for (start = 0; start < MLKEM768_N; start = j + len) { + zeta = zetas[k++]; + for (j = start; j < start + len; j++) { + t = montgomery_reduce((int32_t) zeta * r->coeffs[j + len]); + r->coeffs[j + len] = r->coeffs[j] - t; + r->coeffs[j] = r->coeffs[j] + t; + } + } + } +} + +static void +poly_invntt(poly *r) +{ + unsigned int start, len, j, k; + int16_t t, zeta; + const int16_t f = 1441; + + k = 127; + for (len = 2; len <= 128; len <<= 1) { + for (start = 0; start < MLKEM768_N; start = j + len) { + zeta = zetas[k--]; + for (j = start; j < start + len; j++) { + t = r->coeffs[j]; + r->coeffs[j] = barrett_reduce(t + r->coeffs[j + len]); + r->coeffs[j + len] = montgomery_reduce((int32_t) zeta * (r->coeffs[j + len] - t)); + } + } + } + for (j = 0; j < MLKEM768_N; j++) { + r->coeffs[j] = montgomery_reduce((int32_t) f * r->coeffs[j]); + } +} + +static void +poly_basemul(poly *r, const poly *a, const poly *b) +{ + unsigned int i; + int16_t zeta; + + for (i = 0; i < MLKEM768_N / 4; i++) { + zeta = zetas[64 + i]; + + r->coeffs[4 * i] = montgomery_reduce((int32_t) a->coeffs[4 * i + 1] * b->coeffs[4 * i + 1]); + r->coeffs[4 * i] = montgomery_reduce((int32_t) r->coeffs[4 * i] * zeta); + r->coeffs[4 * i] += montgomery_reduce((int32_t) a->coeffs[4 * i] * b->coeffs[4 * i]); + + r->coeffs[4 * i + 1] = montgomery_reduce((int32_t) a->coeffs[4 * i] * b->coeffs[4 * i + 1]); + r->coeffs[4 * i + 1] += + montgomery_reduce((int32_t) a->coeffs[4 * i + 1] * b->coeffs[4 * i]); + + r->coeffs[4 * i + 2] = + montgomery_reduce((int32_t) a->coeffs[4 * i + 3] * b->coeffs[4 * i + 3]); + r->coeffs[4 * i + 2] = montgomery_reduce((int32_t) r->coeffs[4 * i + 2] * (-zeta)); + r->coeffs[4 * i + 2] += + montgomery_reduce((int32_t) a->coeffs[4 * i + 2] * b->coeffs[4 * i + 2]); + + r->coeffs[4 * i + 3] = + montgomery_reduce((int32_t) a->coeffs[4 * i + 2] * b->coeffs[4 * i + 3]); + r->coeffs[4 * i + 3] += + montgomery_reduce((int32_t) a->coeffs[4 * i + 3] * b->coeffs[4 * i + 2]); + } +} + +static void +poly_tomont(poly *r) +{ + unsigned int i; + const int16_t f = 1353; + + for (i = 0; i < MLKEM768_N; i++) { + r->coeffs[i] = montgomery_reduce((int32_t) f * r->coeffs[i]); + } +} + +static void +poly_reduce(poly *r) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_N; i++) { + r->coeffs[i] = barrett_reduce(r->coeffs[i]); + } +} + +static void +poly_add(poly *r, const poly *a, const poly *b) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_N; i++) { + r->coeffs[i] = a->coeffs[i] + b->coeffs[i]; + } +} + +static void +poly_sub(poly *r, const poly *a, const poly *b) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_N; i++) { + r->coeffs[i] = a->coeffs[i] - b->coeffs[i]; + } +} + +static void +poly_csubq(poly *r) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_N; i++) { + r->coeffs[i] = csubq(r->coeffs[i]); + } +} + +static void +poly_cbd_eta2(poly *r, const unsigned char buf[128]) +{ + unsigned int i, j; + uint32_t t, d; + int16_t a, b; + + for (i = 0; i < MLKEM768_N / 8; i++) { + t = (uint32_t) buf[4 * i] | ((uint32_t) buf[4 * i + 1] << 8) | + ((uint32_t) buf[4 * i + 2] << 16) | ((uint32_t) buf[4 * i + 3] << 24); + + d = t & 0x55555555; + d += (t >> 1) & 0x55555555; + + for (j = 0; j < 8; j++) { + a = (d >> (4 * j)) & 0x3; + b = (d >> (4 * j + 2)) & 0x3; + r->coeffs[8 * i + j] = a - b; + } + } +} + +static void +poly_getnoise_eta2(poly *r, const unsigned char seed[32], uint8_t nonce) +{ + unsigned char buf[MLKEM768_ETA2 * MLKEM768_N / 4]; + crypto_xof_shake256_state state; + unsigned char extseed[33]; + + memcpy(extseed, seed, 32); + extseed[32] = nonce; + + crypto_xof_shake256_init(&state); + crypto_xof_shake256_update(&state, extseed, 33); + crypto_xof_shake256_squeeze(&state, buf, sizeof(buf)); + + poly_cbd_eta2(r, buf); + sodium_memzero(&state, sizeof state); + sodium_memzero(buf, sizeof buf); +} + +static void +poly_frombytes(poly *r, const unsigned char a[MLKEM768_POLYBYTES]) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_N / 2; i++) { + r->coeffs[2 * i] = ((a[3 * i + 0] >> 0) | ((uint16_t) a[3 * i + 1] << 8)) & 0xFFF; + r->coeffs[2 * i + 1] = ((a[3 * i + 1] >> 4) | ((uint16_t) a[3 * i + 2] << 4)) & 0xFFF; + } +} + +static void +poly_tobytes(unsigned char r[MLKEM768_POLYBYTES], const poly *a) +{ + unsigned int i; + uint16_t t0, t1; + + for (i = 0; i < MLKEM768_N / 2; i++) { + t0 = a->coeffs[2 * i]; + t1 = a->coeffs[2 * i + 1]; + r[3 * i + 0] = (unsigned char) (t0 >> 0); + r[3 * i + 1] = (unsigned char) ((t0 >> 8) | (t1 << 4)); + r[3 * i + 2] = (unsigned char) (t1 >> 4); + } +} + +static void +poly_frommsg(poly *r, const unsigned char msg[32]) +{ + unsigned int i, j; + int16_t mask; + + for (i = 0; i < MLKEM768_N / 8; i++) { + for (j = 0; j < 8; j++) { + mask = -((msg[i] >> j) & 1); + r->coeffs[8 * i + j] = mask & ((MLKEM768_Q + 1) / 2); + } + } +} + +static void +poly_tomsg(unsigned char msg[32], const poly *a) +{ + unsigned int i, j; + uint32_t t; + + for (i = 0; i < MLKEM768_N / 8; i++) { + msg[i] = 0; + for (j = 0; j < 8; j++) { + t = (uint32_t) a->coeffs[8 * i + j]; + t += (uint32_t) (((int32_t) a->coeffs[8 * i + j] >> 15) & MLKEM768_Q); + t = (((t << 1) + MLKEM768_Q / 2) * 80635) >> 28; + t &= 1; + msg[i] |= t << j; + } + } +} + +static void +poly_compress_du(unsigned char r[MLKEM768_POLYCOMPRESSEDBYTES_DU], const poly *a) +{ + uint32_t t[4]; + unsigned int i, j; + + for (i = 0; i < MLKEM768_N / 4; i++) { + for (j = 0; j < 4; j++) { + t[j] = (uint32_t) a->coeffs[4 * i + j]; + t[j] += (uint32_t) (((int32_t) a->coeffs[4 * i + j] >> 15) & MLKEM768_Q); + t[j] = (uint32_t) ((((uint64_t) t[j] << 10) + MLKEM768_Q / 2) * 161271ULL >> 29); + t[j] &= 0x3ff; + } + + r[5 * i + 0] = (unsigned char) (t[0] >> 0); + r[5 * i + 1] = (unsigned char) ((t[0] >> 8) | (t[1] << 2)); + r[5 * i + 2] = (unsigned char) ((t[1] >> 6) | (t[2] << 4)); + r[5 * i + 3] = (unsigned char) ((t[2] >> 4) | (t[3] << 6)); + r[5 * i + 4] = (unsigned char) (t[3] >> 2); + } +} + +static void +poly_decompress_du(poly *r, const unsigned char a[MLKEM768_POLYCOMPRESSEDBYTES_DU]) +{ + uint16_t t[4]; + unsigned int i; + + for (i = 0; i < MLKEM768_N / 4; i++) { + t[0] = (a[5 * i + 0] >> 0) | ((uint16_t) a[5 * i + 1] << 8); + t[1] = (a[5 * i + 1] >> 2) | ((uint16_t) a[5 * i + 2] << 6); + t[2] = (a[5 * i + 2] >> 4) | ((uint16_t) a[5 * i + 3] << 4); + t[3] = (a[5 * i + 3] >> 6) | ((uint16_t) a[5 * i + 4] << 2); + + r->coeffs[4 * i + 0] = (int16_t) (((uint32_t) (t[0] & 0x3FF) * MLKEM768_Q + 512) >> 10); + r->coeffs[4 * i + 1] = (int16_t) (((uint32_t) (t[1] & 0x3FF) * MLKEM768_Q + 512) >> 10); + r->coeffs[4 * i + 2] = (int16_t) (((uint32_t) (t[2] & 0x3FF) * MLKEM768_Q + 512) >> 10); + r->coeffs[4 * i + 3] = (int16_t) (((uint32_t) (t[3] & 0x3FF) * MLKEM768_Q + 512) >> 10); + } +} + +static void +poly_compress_dv(unsigned char r[MLKEM768_POLYCOMPRESSEDBYTES_DV], const poly *a) +{ + uint32_t t[8]; + unsigned int i, j; + + for (i = 0; i < MLKEM768_N / 8; i++) { + for (j = 0; j < 8; j++) { + t[j] = (uint32_t) a->coeffs[8 * i + j]; + t[j] += (uint32_t) (((int32_t) a->coeffs[8 * i + j] >> 15) & MLKEM768_Q); + t[j] = (uint32_t) ((((uint64_t) t[j] << 4) + MLKEM768_Q / 2) * 161271ULL >> 29); + t[j] &= 0xf; + } + + r[4 * i + 0] = (unsigned char) (t[0] | (t[1] << 4)); + r[4 * i + 1] = (unsigned char) (t[2] | (t[3] << 4)); + r[4 * i + 2] = (unsigned char) (t[4] | (t[5] << 4)); + r[4 * i + 3] = (unsigned char) (t[6] | (t[7] << 4)); + } +} + +static void +poly_decompress_dv(poly *r, const unsigned char a[MLKEM768_POLYCOMPRESSEDBYTES_DV]) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_N / 2; i++) { + r->coeffs[2 * i + 0] = (int16_t) ((((uint16_t) (a[i] & 15) * MLKEM768_Q) + 8) >> 4); + r->coeffs[2 * i + 1] = (int16_t) ((((uint16_t) (a[i] >> 4) * MLKEM768_Q) + 8) >> 4); + } +} + +static void +polyvec_ntt(polyvec *r) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_K; i++) { + poly_ntt(&r->vec[i]); + } +} + +static void +polyvec_invntt(polyvec *r) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_K; i++) { + poly_invntt(&r->vec[i]); + } +} + +static void +polyvec_basemul_acc(poly *r, const polyvec *a, const polyvec *b) +{ + poly t; + unsigned int i; + + poly_basemul(r, &a->vec[0], &b->vec[0]); + for (i = 1; i < MLKEM768_K; i++) { + poly_basemul(&t, &a->vec[i], &b->vec[i]); + poly_add(r, r, &t); + } + + poly_reduce(r); +} + +static void +polyvec_reduce(polyvec *r) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_K; i++) { + poly_reduce(&r->vec[i]); + } +} + +static void +polyvec_csubq(polyvec *r) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_K; i++) { + poly_csubq(&r->vec[i]); + } +} + +static void +polyvec_add(polyvec *r, const polyvec *a, const polyvec *b) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_K; i++) { + poly_add(&r->vec[i], &a->vec[i], &b->vec[i]); + } +} + +static void +polyvec_tobytes(unsigned char r[MLKEM768_POLYVECBYTES], const polyvec *a) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_K; i++) { + poly_tobytes(r + i * MLKEM768_POLYBYTES, &a->vec[i]); + } +} + +static void +polyvec_frombytes(polyvec *r, const unsigned char a[MLKEM768_POLYVECBYTES]) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_K; i++) { + poly_frombytes(&r->vec[i], a + i * MLKEM768_POLYBYTES); + } +} + +static int +polyvec_is_canonical(const polyvec *a) +{ + unsigned int i, j; + + for (i = 0; i < MLKEM768_K; i++) { + for (j = 0; j < MLKEM768_N; j++) { + if ((uint16_t) a->vec[i].coeffs[j] >= MLKEM768_Q) { + return 0; + } + } + } + return 1; +} + +static void +polyvec_compress(unsigned char r[MLKEM768_POLYVECCOMPRESSEDBYTES_DU], const polyvec *a) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_K; i++) { + poly_compress_du(r + i * MLKEM768_POLYCOMPRESSEDBYTES_DU, &a->vec[i]); + } +} + +static void +polyvec_decompress(polyvec *r, const unsigned char a[MLKEM768_POLYVECCOMPRESSEDBYTES_DU]) +{ + unsigned int i; + + for (i = 0; i < MLKEM768_K; i++) { + poly_decompress_du(&r->vec[i], a + i * MLKEM768_POLYCOMPRESSEDBYTES_DU); + } +} + +static unsigned int +rej_uniform(int16_t *r, unsigned int len, const unsigned char *buf, unsigned int buflen) +{ + unsigned int ctr, pos; + uint16_t val0, val1; + + ctr = pos = 0; + while (ctr < len && pos + 3 <= buflen) { + val0 = ((buf[pos + 0] >> 0) | ((uint16_t) buf[pos + 1] << 8)) & 0xFFF; + val1 = ((buf[pos + 1] >> 4) | ((uint16_t) buf[pos + 2] << 4)) & 0xFFF; + pos += 3; + + if (val0 < MLKEM768_Q) { + r[ctr++] = (int16_t) val0; + } + if (ctr < len && val1 < MLKEM768_Q) { + r[ctr++] = (int16_t) val1; + } + } + + return ctr; +} + +#define GEN_MATRIX_NBLOCKS \ + ((12 * MLKEM768_N / 8 * (1 << 12) / MLKEM768_Q + crypto_xof_shake128_BLOCKBYTES) / \ + crypto_xof_shake128_BLOCKBYTES) + +static void +gen_matrix(polyvec *a, const unsigned char seed[32], int transposed) +{ + crypto_xof_shake128_state state; + unsigned char buf[GEN_MATRIX_NBLOCKS * crypto_xof_shake128_BLOCKBYTES + 2]; + unsigned char extseed[34]; + unsigned int ctr, i, j; + unsigned int buflen; + + memcpy(extseed, seed, 32); + + for (i = 0; i < MLKEM768_K; i++) { + for (j = 0; j < MLKEM768_K; j++) { + if (transposed) { + extseed[32] = (unsigned char) i; + extseed[33] = (unsigned char) j; + } else { + extseed[32] = (unsigned char) j; + extseed[33] = (unsigned char) i; + } + + crypto_xof_shake128_init(&state); + crypto_xof_shake128_update(&state, extseed, 34); + + buflen = GEN_MATRIX_NBLOCKS * crypto_xof_shake128_BLOCKBYTES; + crypto_xof_shake128_squeeze(&state, buf, buflen); + + ctr = rej_uniform(a[i].vec[j].coeffs, MLKEM768_N, buf, buflen); + + while (ctr < MLKEM768_N) { + crypto_xof_shake128_squeeze(&state, buf, crypto_xof_shake128_BLOCKBYTES); + ctr += rej_uniform(a[i].vec[j].coeffs + ctr, MLKEM768_N - ctr, buf, + crypto_xof_shake128_BLOCKBYTES); + } + } + } +} + +static void +indcpa_keypair(unsigned char pk[crypto_kem_mlkem768_PUBLICKEYBYTES], + unsigned char sk[MLKEM768_POLYVECBYTES], + const unsigned char seed[32]) +{ + polyvec a[MLKEM768_K], e, pkpv, skpv; + unsigned char buf[64]; + unsigned char *publicseed = buf; + unsigned char *noiseseed = buf + 32; + unsigned int i; + uint8_t nonce = 0; + + crypto_hash_sha3512(buf, seed, 33); + + gen_matrix(a, publicseed, 0); + + for (i = 0; i < MLKEM768_K; i++) { + poly_getnoise_eta2(&skpv.vec[i], noiseseed, nonce++); + } + for (i = 0; i < MLKEM768_K; i++) { + poly_getnoise_eta2(&e.vec[i], noiseseed, nonce++); + } + + polyvec_ntt(&skpv); + polyvec_ntt(&e); + + for (i = 0; i < MLKEM768_K; i++) { + polyvec_basemul_acc(&pkpv.vec[i], &a[i], &skpv); + poly_tomont(&pkpv.vec[i]); + } + + polyvec_add(&pkpv, &pkpv, &e); + polyvec_reduce(&pkpv); + polyvec_csubq(&pkpv); + polyvec_reduce(&skpv); + polyvec_csubq(&skpv); + + polyvec_tobytes(sk, &skpv); + polyvec_tobytes(pk, &pkpv); + memcpy(pk + MLKEM768_POLYVECBYTES, publicseed, 32); + sodium_memzero(buf, sizeof buf); + sodium_memzero(&skpv, sizeof skpv); + sodium_memzero(&e, sizeof e); +} + +static void +indcpa_enc(unsigned char ct[crypto_kem_mlkem768_CIPHERTEXTBYTES], + const unsigned char m[32], + const unsigned char pk[crypto_kem_mlkem768_PUBLICKEYBYTES], + const unsigned char coins[32]) +{ + polyvec sp, pkpv, ep, at[MLKEM768_K], b; + poly v, k, epp; + unsigned char seed[32]; + unsigned int i; + uint8_t nonce = 0; + + memcpy(seed, pk + MLKEM768_POLYVECBYTES, 32); + + polyvec_frombytes(&pkpv, pk); + + poly_frommsg(&k, m); + + gen_matrix(at, seed, 1); + + for (i = 0; i < MLKEM768_K; i++) { + poly_getnoise_eta2(&sp.vec[i], coins, nonce++); + } + for (i = 0; i < MLKEM768_K; i++) { + poly_getnoise_eta2(&ep.vec[i], coins, nonce++); + } + poly_getnoise_eta2(&epp, coins, nonce++); + + polyvec_ntt(&sp); + polyvec_reduce(&sp); + + for (i = 0; i < MLKEM768_K; i++) { + polyvec_basemul_acc(&b.vec[i], &at[i], &sp); + } + + polyvec_basemul_acc(&v, &pkpv, &sp); + + polyvec_invntt(&b); + poly_invntt(&v); + + polyvec_add(&b, &b, &ep); + poly_add(&v, &v, &epp); + poly_add(&v, &v, &k); + + polyvec_reduce(&b); + poly_reduce(&v); + polyvec_csubq(&b); + poly_csubq(&v); + + polyvec_compress(ct, &b); + poly_compress_dv(ct + MLKEM768_POLYVECCOMPRESSEDBYTES_DU, &v); + sodium_memzero(&sp, sizeof sp); + sodium_memzero(&ep, sizeof ep); + sodium_memzero(&epp, sizeof epp); + sodium_memzero(&k, sizeof k); +} + +static void +indcpa_dec(unsigned char m[32], + const unsigned char ct[crypto_kem_mlkem768_CIPHERTEXTBYTES], + const unsigned char sk[MLKEM768_POLYVECBYTES]) +{ + polyvec b, skpv; + poly v, mp; + + polyvec_decompress(&b, ct); + poly_decompress_dv(&v, ct + MLKEM768_POLYVECCOMPRESSEDBYTES_DU); + + polyvec_frombytes(&skpv, sk); + + polyvec_ntt(&b); + polyvec_reduce(&b); + polyvec_basemul_acc(&mp, &skpv, &b); + poly_invntt(&mp); + + poly_sub(&mp, &v, &mp); + poly_reduce(&mp); + poly_csubq(&mp); + + poly_tomsg(m, &mp); + sodium_memzero(&skpv, sizeof skpv); + sodium_memzero(&mp, sizeof mp); +} + +static void +cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) +{ + size_t i; + unsigned char mask; + + mask = (unsigned char) (-(int) b); + +#ifdef HAVE_INLINE_ASM + __asm__ __volatile__("" : "+r"(mask)); +#endif + + for (i = 0; i < len; i++) { + r[i] ^= mask & (r[i] ^ x[i]); + } +} + +int +mlkem768_ref_seed_keypair(unsigned char *pk, unsigned char *sk, const unsigned char *seed) +{ + unsigned char indseed[33]; + + memcpy(indseed, seed, 32); + indseed[32] = MLKEM768_K; + + indcpa_keypair(pk, sk, indseed); + sodium_memzero(indseed, sizeof indseed); + memcpy(sk + MLKEM768_POLYVECBYTES, pk, crypto_kem_mlkem768_PUBLICKEYBYTES); + crypto_hash_sha3256(sk + MLKEM768_POLYVECBYTES + crypto_kem_mlkem768_PUBLICKEYBYTES, pk, + crypto_kem_mlkem768_PUBLICKEYBYTES); + memcpy(sk + MLKEM768_POLYVECBYTES + crypto_kem_mlkem768_PUBLICKEYBYTES + 32, seed + 32, 32); + + return 0; +} + +int +mlkem768_ref_keypair(unsigned char *pk, unsigned char *sk) +{ + unsigned char seed[crypto_kem_mlkem768_SEEDBYTES]; + + randombytes_buf(seed, crypto_kem_mlkem768_SEEDBYTES); + return mlkem768_ref_seed_keypair(pk, sk, seed); +} + +int +mlkem768_ref_enc_deterministic(unsigned char *ct, unsigned char *ss, const unsigned char *pk, + const unsigned char *seed) +{ + polyvec pkpv; + unsigned char buf[64]; + unsigned char kr[64]; + + polyvec_frombytes(&pkpv, pk); + if (polyvec_is_canonical(&pkpv) == 0) { + return -1; + } + + memcpy(buf, seed, 32); + crypto_hash_sha3256(buf + 32, pk, crypto_kem_mlkem768_PUBLICKEYBYTES); + + crypto_hash_sha3512(kr, buf, 64); + + indcpa_enc(ct, buf, pk, kr + 32); + + memcpy(ss, kr, crypto_kem_mlkem768_SHAREDSECRETBYTES); + sodium_memzero(buf, sizeof buf); + sodium_memzero(kr, sizeof kr); + + return 0; +} + +int +mlkem768_ref_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) +{ + unsigned char seed[32]; + + randombytes_buf(seed, 32); + return mlkem768_ref_enc_deterministic(ct, ss, pk, seed); +} + +int +mlkem768_ref_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) +{ + unsigned char buf[64]; + unsigned char kr[64]; + unsigned char k_bar[crypto_kem_mlkem768_SHAREDSECRETBYTES]; + unsigned char cmp[crypto_kem_mlkem768_CIPHERTEXTBYTES]; + const unsigned char *pk = sk + MLKEM768_POLYVECBYTES; + const unsigned char *hpk = sk + MLKEM768_POLYVECBYTES + crypto_kem_mlkem768_PUBLICKEYBYTES; + const unsigned char *z = sk + MLKEM768_POLYVECBYTES + crypto_kem_mlkem768_PUBLICKEYBYTES + 32; + int fail; + unsigned int fail_mask; + crypto_xof_shake256_state state; + + indcpa_dec(buf, ct, sk); + + memcpy(buf + 32, hpk, 32); + + crypto_hash_sha3512(kr, buf, 64); + + indcpa_enc(cmp, buf, pk, kr + 32); + + fail = sodium_memcmp(ct, cmp, crypto_kem_mlkem768_CIPHERTEXTBYTES); + fail_mask = (unsigned int) fail; + fail_mask >>= (sizeof(fail_mask) * 8U - 1U); + + crypto_xof_shake256_init(&state); + crypto_xof_shake256_update(&state, z, 32); + crypto_xof_shake256_update(&state, ct, crypto_kem_mlkem768_CIPHERTEXTBYTES); + crypto_xof_shake256_squeeze(&state, k_bar, crypto_kem_mlkem768_SHAREDSECRETBYTES); + + cmov(kr, k_bar, crypto_kem_mlkem768_SHAREDSECRETBYTES, (unsigned char) fail_mask); + + memcpy(ss, kr, crypto_kem_mlkem768_SHAREDSECRETBYTES); + sodium_memzero(buf, sizeof buf); + sodium_memzero(kr, sizeof kr); + sodium_memzero(k_bar, sizeof k_bar); + sodium_memzero(cmp, sizeof cmp); + sodium_memzero(&state, sizeof state); + + return 0; +} diff --git a/src/libsodium/crypto_kem/mlkem768/ref/kem_mlkem768_ref.h b/src/libsodium/crypto_kem/mlkem768/ref/kem_mlkem768_ref.h new file mode 100644 index 00000000..e453d73d --- /dev/null +++ b/src/libsodium/crypto_kem/mlkem768/ref/kem_mlkem768_ref.h @@ -0,0 +1,20 @@ +#ifndef kem_mlkem768_ref_H +#define kem_mlkem768_ref_H + +#include +#include + +#include "private/quirks.h" + +int mlkem768_ref_keypair(unsigned char *pk, unsigned char *sk); + +int mlkem768_ref_seed_keypair(unsigned char *pk, unsigned char *sk, const unsigned char *seed); + +int mlkem768_ref_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk); + +int mlkem768_ref_enc_deterministic(unsigned char *ct, unsigned char *ss, const unsigned char *pk, + const unsigned char *seed); + +int mlkem768_ref_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk); + +#endif diff --git a/src/libsodium/include/Makefile.am b/src/libsodium/include/Makefile.am index 0d9f61be..d411a242 100644 --- a/src/libsodium/include/Makefile.am +++ b/src/libsodium/include/Makefile.am @@ -33,6 +33,7 @@ SODIUM_EXPORT = \ sodium/crypto_kdf_hkdf_sha256.h \ sodium/crypto_kdf_hkdf_sha512.h \ sodium/crypto_kdf_blake2b.h \ + sodium/crypto_kem_mlkem768.h \ sodium/crypto_kx.h \ sodium/crypto_onetimeauth.h \ sodium/crypto_onetimeauth_poly1305.h \ diff --git a/src/libsodium/include/Makefile.in b/src/libsodium/include/Makefile.in index 66c34d64..092fd02d 100644 --- a/src/libsodium/include/Makefile.in +++ b/src/libsodium/include/Makefile.in @@ -376,6 +376,7 @@ SODIUM_EXPORT = \ sodium/crypto_generichash_blake2b.h \ sodium/crypto_hash.h \ sodium/crypto_hash_sha256.h \ + sodium/crypto_hash_sha3.h \ sodium/crypto_hash_sha512.h \ sodium/crypto_ipcrypt.h \ sodium/crypto_kdf.h \ diff --git a/src/libsodium/include/sodium.h b/src/libsodium/include/sodium.h index 9733eb5f..43015093 100644 --- a/src/libsodium/include/sodium.h +++ b/src/libsodium/include/sodium.h @@ -33,6 +33,7 @@ #include "sodium/crypto_kdf_blake2b.h" #include "sodium/crypto_kdf_hkdf_sha256.h" #include "sodium/crypto_kdf_hkdf_sha512.h" +#include "sodium/crypto_kem_mlkem768.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_mlkem768.h b/src/libsodium/include/sodium/crypto_kem_mlkem768.h new file mode 100644 index 00000000..31b5f936 --- /dev/null +++ b/src/libsodium/include/sodium/crypto_kem_mlkem768.h @@ -0,0 +1,70 @@ +#ifndef crypto_kem_mlkem768_H +#define crypto_kem_mlkem768_H + +#include + +#include "export.h" + +#ifdef __cplusplus +# ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wlong-long" +# endif +extern "C" { +#endif + +#define crypto_kem_mlkem768_PUBLICKEYBYTES 1184U +SODIUM_EXPORT +size_t crypto_kem_mlkem768_publickeybytes(void); + +#define crypto_kem_mlkem768_SECRETKEYBYTES 2400U +SODIUM_EXPORT +size_t crypto_kem_mlkem768_secretkeybytes(void); + +#define crypto_kem_mlkem768_CIPHERTEXTBYTES 1088U +SODIUM_EXPORT +size_t crypto_kem_mlkem768_ciphertextbytes(void); + +#define crypto_kem_mlkem768_SHAREDSECRETBYTES 32U +SODIUM_EXPORT +size_t crypto_kem_mlkem768_sharedsecretbytes(void); + +#define crypto_kem_mlkem768_SEEDBYTES 64U +SODIUM_EXPORT +size_t crypto_kem_mlkem768_seedbytes(void); + +SODIUM_EXPORT +int crypto_kem_mlkem768_seed_keypair(unsigned char pk[crypto_kem_mlkem768_PUBLICKEYBYTES], + unsigned char sk[crypto_kem_mlkem768_SECRETKEYBYTES], + const unsigned char seed[crypto_kem_mlkem768_SEEDBYTES]) + __attribute__((nonnull)); + +SODIUM_EXPORT +int crypto_kem_mlkem768_keypair(unsigned char pk[crypto_kem_mlkem768_PUBLICKEYBYTES], + unsigned char sk[crypto_kem_mlkem768_SECRETKEYBYTES]) + __attribute__((nonnull)); + +SODIUM_EXPORT +int crypto_kem_mlkem768_enc(unsigned char ct[crypto_kem_mlkem768_CIPHERTEXTBYTES], + unsigned char ss[crypto_kem_mlkem768_SHAREDSECRETBYTES], + const unsigned char pk[crypto_kem_mlkem768_PUBLICKEYBYTES]) + __attribute__((warn_unused_result)) __attribute__((nonnull)); + +SODIUM_EXPORT +int +crypto_kem_mlkem768_enc_deterministic(unsigned char ct[crypto_kem_mlkem768_CIPHERTEXTBYTES], + unsigned char ss[crypto_kem_mlkem768_SHAREDSECRETBYTES], + const unsigned char pk[crypto_kem_mlkem768_PUBLICKEYBYTES], + const unsigned char seed[32]) + __attribute__((warn_unused_result)) __attribute__((nonnull)); + +SODIUM_EXPORT +int crypto_kem_mlkem768_dec(unsigned char ss[crypto_kem_mlkem768_SHAREDSECRETBYTES], + const unsigned char ct[crypto_kem_mlkem768_CIPHERTEXTBYTES], + const unsigned char sk[crypto_kem_mlkem768_SECRETKEYBYTES]) + __attribute__((warn_unused_result)) __attribute__((nonnull)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/libsodium/include/sodium/private/quirks.h b/src/libsodium/include/sodium/private/quirks.h index 61a52000..372f981a 100644 --- a/src/libsodium/include/sodium/private/quirks.h +++ b/src/libsodium/include/sodium/private/quirks.h @@ -13,6 +13,11 @@ #define keccak1600_ref_permute_12 _sodium_keccak1600_ref_permute_12 #define keccak1600_ref_permute_24 _sodium_keccak1600_ref_permute_24 #define keccak1600_ref_xor_bytes _sodium_keccak1600_ref_xor_bytes +#define mlkem768_ref_dec _sodium_mlkem768_ref_dec +#define mlkem768_ref_enc _sodium_mlkem768_ref_enc +#define mlkem768_ref_enc_deterministic _sodium_mlkem768_ref_enc_deterministic +#define mlkem768_ref_keypair _sodium_mlkem768_ref_keypair +#define mlkem768_ref_seed_keypair _sodium_mlkem768_ref_seed_keypair #define shake128_ref _sodium_shake128_ref #define shake128_ref_init _sodium_shake128_ref_init #define shake128_ref_init_with_domain _sodium_shake128_ref_init_with_domain diff --git a/test/default/Makefile.am b/test/default/Makefile.am index 523472ab..b1d0ff79 100644 --- a/test/default/Makefile.am +++ b/test/default/Makefile.am @@ -264,6 +264,7 @@ TESTS_TARGETS = \ hash_sha3512 \ ipcrypt \ kdf \ + kem_mlkem768 \ keygen \ kx \ metamorphic \ diff --git a/test/default/Makefile.in b/test/default/Makefile.in index 4a1c2207..c657354e 100644 --- a/test/default/Makefile.in +++ b/test/default/Makefile.in @@ -92,7 +92,8 @@ host_triplet = @host@ target_triplet = @target@ @EMSCRIPTEN_FALSE@am__append_1 = \ @EMSCRIPTEN_FALSE@ sodium_utils2 \ -@EMSCRIPTEN_FALSE@ sodium_utils3 +@EMSCRIPTEN_FALSE@ sodium_utils3 \ +@EMSCRIPTEN_FALSE@ sodium_utils4 check_PROGRAMS = $(am__EXEEXT_3) TESTS = $(am__EXEEXT_3) @@ -102,8 +103,10 @@ TESTS = $(am__EXEEXT_3) @MINIMAL_FALSE@ kdf_hkdf \ @MINIMAL_FALSE@ kdf_hkdf2 \ @MINIMAL_FALSE@ kdf_hkdf3 \ +@MINIMAL_FALSE@ kdf_hkdf4 \ @MINIMAL_FALSE@ pwhash_scrypt \ @MINIMAL_FALSE@ stream5 \ +@MINIMAL_FALSE@ stream6 \ @MINIMAL_FALSE@ pwhash_scrypt_ll \ @MINIMAL_FALSE@ scalarmult_ed25519 \ @MINIMAL_FALSE@ scalarmult_ristretto255 \ @@ -131,11 +134,13 @@ mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @EMSCRIPTEN_FALSE@am__EXEEXT_1 = sodium_utils2$(EXEEXT) \ -@EMSCRIPTEN_FALSE@ sodium_utils3$(EXEEXT) +@EMSCRIPTEN_FALSE@ sodium_utils3$(EXEEXT) \ +@EMSCRIPTEN_FALSE@ sodium_utils4$(EXEEXT) @MINIMAL_FALSE@am__EXEEXT_2 = core_ed25519$(EXEEXT) \ @MINIMAL_FALSE@ core_ristretto255$(EXEEXT) kdf_hkdf$(EXEEXT) \ @MINIMAL_FALSE@ kdf_hkdf2$(EXEEXT) kdf_hkdf3$(EXEEXT) \ -@MINIMAL_FALSE@ pwhash_scrypt$(EXEEXT) stream5$(EXEEXT) \ +@MINIMAL_FALSE@ kdf_hkdf4$(EXEEXT) pwhash_scrypt$(EXEEXT) \ +@MINIMAL_FALSE@ stream5$(EXEEXT) stream6$(EXEEXT) \ @MINIMAL_FALSE@ pwhash_scrypt_ll$(EXEEXT) \ @MINIMAL_FALSE@ scalarmult_ed25519$(EXEEXT) \ @MINIMAL_FALSE@ scalarmult_ristretto255$(EXEEXT) \ @@ -148,20 +153,21 @@ am__EXEEXT_3 = aead_aegis128l$(EXEEXT) aead_aegis256$(EXEEXT) \ box$(EXEEXT) box2$(EXEEXT) box7$(EXEEXT) box8$(EXEEXT) \ box_easy$(EXEEXT) box_easy2$(EXEEXT) box_seal$(EXEEXT) \ box_seed$(EXEEXT) chacha20$(EXEEXT) codecs$(EXEEXT) \ - codecs2$(EXEEXT) core_keccak1600$(EXEEXT) core1$(EXEEXT) \ - core2$(EXEEXT) core3$(EXEEXT) core4$(EXEEXT) core5$(EXEEXT) \ - core6$(EXEEXT) ed25519_convert$(EXEEXT) generichash$(EXEEXT) \ - generichash2$(EXEEXT) generichash3$(EXEEXT) hash$(EXEEXT) \ - hash3$(EXEEXT) ipcrypt$(EXEEXT) kdf$(EXEEXT) keygen$(EXEEXT) \ - kx$(EXEEXT) metamorphic$(EXEEXT) misuse$(EXEEXT) \ - onetimeauth$(EXEEXT) onetimeauth2$(EXEEXT) \ + codecs2$(EXEEXT) codecs3$(EXEEXT) core_keccak1600$(EXEEXT) \ + core1$(EXEEXT) core2$(EXEEXT) core3$(EXEEXT) core4$(EXEEXT) \ + core5$(EXEEXT) core6$(EXEEXT) ed25519_convert$(EXEEXT) \ + generichash$(EXEEXT) generichash2$(EXEEXT) \ + generichash3$(EXEEXT) hash$(EXEEXT) hash3$(EXEEXT) \ + hash_sha3256$(EXEEXT) hash_sha3512$(EXEEXT) ipcrypt$(EXEEXT) \ + kdf$(EXEEXT) keygen$(EXEEXT) kx$(EXEEXT) metamorphic$(EXEEXT) \ + misuse$(EXEEXT) onetimeauth$(EXEEXT) onetimeauth2$(EXEEXT) \ onetimeauth7$(EXEEXT) pwhash_argon2i$(EXEEXT) \ - pwhash_argon2id$(EXEEXT) randombytes$(EXEEXT) \ - scalarmult$(EXEEXT) scalarmult2$(EXEEXT) scalarmult5$(EXEEXT) \ - scalarmult6$(EXEEXT) scalarmult7$(EXEEXT) scalarmult8$(EXEEXT) \ - secretbox$(EXEEXT) secretbox2$(EXEEXT) secretbox7$(EXEEXT) \ - secretbox8$(EXEEXT) secretbox_easy$(EXEEXT) \ - secretbox_easy2$(EXEEXT) \ + pwhash_argon2id$(EXEEXT) pwhash_argon2id2$(EXEEXT) \ + randombytes$(EXEEXT) scalarmult$(EXEEXT) scalarmult2$(EXEEXT) \ + scalarmult5$(EXEEXT) scalarmult6$(EXEEXT) scalarmult7$(EXEEXT) \ + scalarmult8$(EXEEXT) secretbox$(EXEEXT) secretbox2$(EXEEXT) \ + secretbox7$(EXEEXT) secretbox8$(EXEEXT) \ + secretbox_easy$(EXEEXT) secretbox_easy2$(EXEEXT) \ secretstream_xchacha20poly1305$(EXEEXT) shorthash$(EXEEXT) \ sign$(EXEEXT) sodium_core$(EXEEXT) sodium_utils$(EXEEXT) \ sodium_version$(EXEEXT) stream$(EXEEXT) stream2$(EXEEXT) \ @@ -245,6 +251,9 @@ codecs_DEPENDENCIES = $(TESTS_LDADD) codecs2_SOURCES = codecs2.c codecs2_OBJECTS = codecs2.$(OBJEXT) codecs2_DEPENDENCIES = $(TESTS_LDADD) +codecs3_SOURCES = codecs3.c +codecs3_OBJECTS = codecs3.$(OBJEXT) +codecs3_DEPENDENCIES = $(TESTS_LDADD) core1_SOURCES = core1.c core1_OBJECTS = core1.$(OBJEXT) core1_DEPENDENCIES = $(TESTS_LDADD) @@ -290,6 +299,12 @@ hash_DEPENDENCIES = $(TESTS_LDADD) hash3_SOURCES = hash3.c hash3_OBJECTS = hash3.$(OBJEXT) hash3_DEPENDENCIES = $(TESTS_LDADD) +hash_sha3256_SOURCES = hash_sha3256.c +hash_sha3256_OBJECTS = hash_sha3256.$(OBJEXT) +hash_sha3256_DEPENDENCIES = $(TESTS_LDADD) +hash_sha3512_SOURCES = hash_sha3512.c +hash_sha3512_OBJECTS = hash_sha3512.$(OBJEXT) +hash_sha3512_DEPENDENCIES = $(TESTS_LDADD) ipcrypt_SOURCES = ipcrypt.c ipcrypt_OBJECTS = ipcrypt.$(OBJEXT) ipcrypt_DEPENDENCIES = $(TESTS_LDADD) @@ -305,6 +320,9 @@ kdf_hkdf2_DEPENDENCIES = $(TESTS_LDADD) kdf_hkdf3_SOURCES = kdf_hkdf3.c kdf_hkdf3_OBJECTS = kdf_hkdf3.$(OBJEXT) kdf_hkdf3_DEPENDENCIES = $(TESTS_LDADD) +kdf_hkdf4_SOURCES = kdf_hkdf4.c +kdf_hkdf4_OBJECTS = kdf_hkdf4.$(OBJEXT) +kdf_hkdf4_DEPENDENCIES = $(TESTS_LDADD) keygen_SOURCES = keygen.c keygen_OBJECTS = keygen.$(OBJEXT) keygen_DEPENDENCIES = $(TESTS_LDADD) @@ -332,6 +350,9 @@ pwhash_argon2i_DEPENDENCIES = $(TESTS_LDADD) pwhash_argon2id_SOURCES = pwhash_argon2id.c pwhash_argon2id_OBJECTS = pwhash_argon2id.$(OBJEXT) pwhash_argon2id_DEPENDENCIES = $(TESTS_LDADD) +pwhash_argon2id2_SOURCES = pwhash_argon2id2.c +pwhash_argon2id2_OBJECTS = pwhash_argon2id2.$(OBJEXT) +pwhash_argon2id2_DEPENDENCIES = $(TESTS_LDADD) pwhash_scrypt_SOURCES = pwhash_scrypt.c pwhash_scrypt_OBJECTS = pwhash_scrypt.$(OBJEXT) pwhash_scrypt_DEPENDENCIES = $(TESTS_LDADD) @@ -409,6 +430,9 @@ sodium_utils2_DEPENDENCIES = $(TESTS_LDADD) sodium_utils3_SOURCES = sodium_utils3.c sodium_utils3_OBJECTS = sodium_utils3.$(OBJEXT) sodium_utils3_DEPENDENCIES = $(TESTS_LDADD) +sodium_utils4_SOURCES = sodium_utils4.c +sodium_utils4_OBJECTS = sodium_utils4.$(OBJEXT) +sodium_utils4_DEPENDENCIES = $(TESTS_LDADD) sodium_version_SOURCES = sodium_version.c sodium_version_OBJECTS = sodium_version.$(OBJEXT) sodium_version_DEPENDENCIES = $(TESTS_LDADD) @@ -427,6 +451,9 @@ stream4_DEPENDENCIES = $(TESTS_LDADD) stream5_SOURCES = stream5.c stream5_OBJECTS = stream5.$(OBJEXT) stream5_DEPENDENCIES = $(TESTS_LDADD) +stream6_SOURCES = stream6.c +stream6_OBJECTS = stream6.$(OBJEXT) +stream6_DEPENDENCIES = $(TESTS_LDADD) verify1_SOURCES = verify1.c verify1_OBJECTS = verify1.$(OBJEXT) verify1_DEPENDENCIES = $(TESTS_LDADD) @@ -475,21 +502,23 @@ am__depfiles_remade = ./$(DEPDIR)/aead_aegis128l.Po \ ./$(DEPDIR)/box_easy.Po ./$(DEPDIR)/box_easy2.Po \ ./$(DEPDIR)/box_seal.Po ./$(DEPDIR)/box_seed.Po \ ./$(DEPDIR)/chacha20.Po ./$(DEPDIR)/codecs.Po \ - ./$(DEPDIR)/codecs2.Po ./$(DEPDIR)/core1.Po \ - ./$(DEPDIR)/core2.Po ./$(DEPDIR)/core3.Po ./$(DEPDIR)/core4.Po \ - ./$(DEPDIR)/core5.Po ./$(DEPDIR)/core6.Po \ + ./$(DEPDIR)/codecs2.Po ./$(DEPDIR)/codecs3.Po \ + ./$(DEPDIR)/core1.Po ./$(DEPDIR)/core2.Po ./$(DEPDIR)/core3.Po \ + ./$(DEPDIR)/core4.Po ./$(DEPDIR)/core5.Po ./$(DEPDIR)/core6.Po \ ./$(DEPDIR)/core_ed25519.Po ./$(DEPDIR)/core_keccak1600.Po \ ./$(DEPDIR)/core_ristretto255.Po \ ./$(DEPDIR)/ed25519_convert.Po ./$(DEPDIR)/generichash.Po \ ./$(DEPDIR)/generichash2.Po ./$(DEPDIR)/generichash3.Po \ ./$(DEPDIR)/hash.Po ./$(DEPDIR)/hash3.Po \ + ./$(DEPDIR)/hash_sha3256.Po ./$(DEPDIR)/hash_sha3512.Po \ ./$(DEPDIR)/ipcrypt.Po ./$(DEPDIR)/kdf.Po \ ./$(DEPDIR)/kdf_hkdf.Po ./$(DEPDIR)/kdf_hkdf2.Po \ - ./$(DEPDIR)/kdf_hkdf3.Po ./$(DEPDIR)/keygen.Po \ - ./$(DEPDIR)/kx.Po ./$(DEPDIR)/metamorphic.Po \ - ./$(DEPDIR)/misuse.Po ./$(DEPDIR)/onetimeauth.Po \ - ./$(DEPDIR)/onetimeauth2.Po ./$(DEPDIR)/onetimeauth7.Po \ - ./$(DEPDIR)/pwhash_argon2i.Po ./$(DEPDIR)/pwhash_argon2id.Po \ + ./$(DEPDIR)/kdf_hkdf3.Po ./$(DEPDIR)/kdf_hkdf4.Po \ + ./$(DEPDIR)/keygen.Po ./$(DEPDIR)/kx.Po \ + ./$(DEPDIR)/metamorphic.Po ./$(DEPDIR)/misuse.Po \ + ./$(DEPDIR)/onetimeauth.Po ./$(DEPDIR)/onetimeauth2.Po \ + ./$(DEPDIR)/onetimeauth7.Po ./$(DEPDIR)/pwhash_argon2i.Po \ + ./$(DEPDIR)/pwhash_argon2id.Po ./$(DEPDIR)/pwhash_argon2id2.Po \ ./$(DEPDIR)/pwhash_scrypt.Po ./$(DEPDIR)/pwhash_scrypt_ll.Po \ ./$(DEPDIR)/randombytes.Po ./$(DEPDIR)/scalarmult.Po \ ./$(DEPDIR)/scalarmult2.Po ./$(DEPDIR)/scalarmult5.Po \ @@ -503,10 +532,11 @@ am__depfiles_remade = ./$(DEPDIR)/aead_aegis128l.Po \ ./$(DEPDIR)/shorthash.Po ./$(DEPDIR)/sign.Po \ ./$(DEPDIR)/siphashx24.Po ./$(DEPDIR)/sodium_core.Po \ ./$(DEPDIR)/sodium_utils.Po ./$(DEPDIR)/sodium_utils2.Po \ - ./$(DEPDIR)/sodium_utils3.Po ./$(DEPDIR)/sodium_version.Po \ - ./$(DEPDIR)/stream.Po ./$(DEPDIR)/stream2.Po \ - ./$(DEPDIR)/stream3.Po ./$(DEPDIR)/stream4.Po \ - ./$(DEPDIR)/stream5.Po ./$(DEPDIR)/verify1.Po \ + ./$(DEPDIR)/sodium_utils3.Po ./$(DEPDIR)/sodium_utils4.Po \ + ./$(DEPDIR)/sodium_version.Po ./$(DEPDIR)/stream.Po \ + ./$(DEPDIR)/stream2.Po ./$(DEPDIR)/stream3.Po \ + ./$(DEPDIR)/stream4.Po ./$(DEPDIR)/stream5.Po \ + ./$(DEPDIR)/stream6.Po ./$(DEPDIR)/verify1.Po \ ./$(DEPDIR)/xchacha20.Po ./$(DEPDIR)/xof2.Po \ ./$(DEPDIR)/xof_shake128.Po ./$(DEPDIR)/xof_shake256.Po \ ./$(DEPDIR)/xof_turboshake128.Po \ @@ -535,21 +565,23 @@ SOURCES = aead_aegis128l.c aead_aegis256.c aead_aes256gcm.c \ aead_chacha20poly13052.c aead_xchacha20poly1305.c auth.c \ auth2.c auth3.c auth5.c auth6.c auth7.c box.c box2.c box7.c \ box8.c box_easy.c box_easy2.c box_seal.c box_seed.c chacha20.c \ - codecs.c codecs2.c core1.c core2.c core3.c core4.c core5.c \ - core6.c core_ed25519.c core_keccak1600.c core_ristretto255.c \ - ed25519_convert.c generichash.c generichash2.c generichash3.c \ - hash.c hash3.c ipcrypt.c kdf.c kdf_hkdf.c kdf_hkdf2.c \ - kdf_hkdf3.c keygen.c kx.c metamorphic.c misuse.c onetimeauth.c \ - onetimeauth2.c onetimeauth7.c pwhash_argon2i.c \ - pwhash_argon2id.c pwhash_scrypt.c pwhash_scrypt_ll.c \ - randombytes.c scalarmult.c scalarmult2.c scalarmult5.c \ - scalarmult6.c scalarmult7.c scalarmult8.c scalarmult_ed25519.c \ - scalarmult_ristretto255.c secretbox.c secretbox2.c \ - secretbox7.c secretbox8.c secretbox_easy.c secretbox_easy2.c \ - secretstream_xchacha20poly1305.c shorthash.c sign.c \ - siphashx24.c sodium_core.c sodium_utils.c sodium_utils2.c \ - sodium_utils3.c sodium_version.c stream.c stream2.c stream3.c \ - stream4.c stream5.c verify1.c xchacha20.c xof2.c \ + codecs.c codecs2.c codecs3.c core1.c core2.c core3.c core4.c \ + core5.c core6.c core_ed25519.c core_keccak1600.c \ + core_ristretto255.c ed25519_convert.c generichash.c \ + generichash2.c generichash3.c hash.c hash3.c hash_sha3256.c \ + hash_sha3512.c ipcrypt.c kdf.c kdf_hkdf.c kdf_hkdf2.c \ + kdf_hkdf3.c kdf_hkdf4.c keygen.c kx.c metamorphic.c misuse.c \ + onetimeauth.c onetimeauth2.c onetimeauth7.c pwhash_argon2i.c \ + pwhash_argon2id.c pwhash_argon2id2.c pwhash_scrypt.c \ + pwhash_scrypt_ll.c randombytes.c scalarmult.c scalarmult2.c \ + scalarmult5.c scalarmult6.c scalarmult7.c scalarmult8.c \ + scalarmult_ed25519.c scalarmult_ristretto255.c secretbox.c \ + secretbox2.c secretbox7.c secretbox8.c secretbox_easy.c \ + secretbox_easy2.c secretstream_xchacha20poly1305.c shorthash.c \ + sign.c siphashx24.c sodium_core.c sodium_utils.c \ + sodium_utils2.c sodium_utils3.c sodium_utils4.c \ + sodium_version.c stream.c stream2.c stream3.c stream4.c \ + stream5.c stream6.c verify1.c xchacha20.c xof2.c \ xof_shake128.c xof_shake256.c xof_turboshake128.c \ xof_turboshake256.c DIST_SOURCES = aead_aegis128l.c aead_aegis256.c aead_aes256gcm.c \ @@ -557,21 +589,23 @@ DIST_SOURCES = aead_aegis128l.c aead_aegis256.c aead_aes256gcm.c \ aead_chacha20poly13052.c aead_xchacha20poly1305.c auth.c \ auth2.c auth3.c auth5.c auth6.c auth7.c box.c box2.c box7.c \ box8.c box_easy.c box_easy2.c box_seal.c box_seed.c chacha20.c \ - codecs.c codecs2.c core1.c core2.c core3.c core4.c core5.c \ - core6.c core_ed25519.c core_keccak1600.c core_ristretto255.c \ - ed25519_convert.c generichash.c generichash2.c generichash3.c \ - hash.c hash3.c ipcrypt.c kdf.c kdf_hkdf.c kdf_hkdf2.c \ - kdf_hkdf3.c keygen.c kx.c metamorphic.c misuse.c onetimeauth.c \ - onetimeauth2.c onetimeauth7.c pwhash_argon2i.c \ - pwhash_argon2id.c pwhash_scrypt.c pwhash_scrypt_ll.c \ - randombytes.c scalarmult.c scalarmult2.c scalarmult5.c \ - scalarmult6.c scalarmult7.c scalarmult8.c scalarmult_ed25519.c \ - scalarmult_ristretto255.c secretbox.c secretbox2.c \ - secretbox7.c secretbox8.c secretbox_easy.c secretbox_easy2.c \ - secretstream_xchacha20poly1305.c shorthash.c sign.c \ - siphashx24.c sodium_core.c sodium_utils.c sodium_utils2.c \ - sodium_utils3.c sodium_version.c stream.c stream2.c stream3.c \ - stream4.c stream5.c verify1.c xchacha20.c xof2.c \ + codecs.c codecs2.c codecs3.c core1.c core2.c core3.c core4.c \ + core5.c core6.c core_ed25519.c core_keccak1600.c \ + core_ristretto255.c ed25519_convert.c generichash.c \ + generichash2.c generichash3.c hash.c hash3.c hash_sha3256.c \ + hash_sha3512.c ipcrypt.c kdf.c kdf_hkdf.c kdf_hkdf2.c \ + kdf_hkdf3.c kdf_hkdf4.c keygen.c kx.c metamorphic.c misuse.c \ + onetimeauth.c onetimeauth2.c onetimeauth7.c pwhash_argon2i.c \ + pwhash_argon2id.c pwhash_argon2id2.c pwhash_scrypt.c \ + pwhash_scrypt_ll.c randombytes.c scalarmult.c scalarmult2.c \ + scalarmult5.c scalarmult6.c scalarmult7.c scalarmult8.c \ + scalarmult_ed25519.c scalarmult_ristretto255.c secretbox.c \ + secretbox2.c secretbox7.c secretbox8.c secretbox_easy.c \ + secretbox_easy2.c secretstream_xchacha20poly1305.c shorthash.c \ + sign.c siphashx24.c sodium_core.c sodium_utils.c \ + sodium_utils2.c sodium_utils3.c sodium_utils4.c \ + sodium_version.c stream.c stream2.c stream3.c stream4.c \ + stream5.c stream6.c verify1.c xchacha20.c xof2.c \ xof_shake128.c xof_shake256.c xof_turboshake128.c \ xof_turboshake256.c am__can_run_installinfo = \ @@ -1011,6 +1045,7 @@ EXTRA_DIST = \ chacha20.exp \ codecs.exp \ codecs2.exp \ + codecs3.exp \ core_ed25519.exp \ core_keccak1600.exp \ core_ristretto255.exp \ @@ -1026,11 +1061,17 @@ EXTRA_DIST = \ generichash3.exp \ hash.exp \ hash3.exp \ + hash_sha3256.exp \ + hash_sha3512.exp \ ipcrypt.exp \ kdf.exp \ kdf_hkdf.exp \ kdf_hkdf2.exp \ kdf_hkdf3.exp \ + kdf_hkdf4.exp \ + kem.exp \ + kem_mlkem768.exp \ + kem_xwing.exp \ keygen.exp \ kx.exp \ metamorphic.exp \ @@ -1040,6 +1081,7 @@ EXTRA_DIST = \ onetimeauth7.exp \ pwhash_argon2i.exp \ pwhash_argon2id.exp \ + pwhash_argon2id2.exp \ pwhash_scrypt.exp \ pwhash_scrypt_ll.exp \ randombytes.exp \ @@ -1065,12 +1107,14 @@ EXTRA_DIST = \ sodium_utils.exp \ sodium_utils2.exp \ sodium_utils3.exp \ + sodium_utils4.exp \ sodium_version.exp \ stream.exp \ stream2.exp \ stream3.exp \ stream4.exp \ stream5.exp \ + stream6.exp \ verify1.exp \ xchacha20.exp \ xof_shake128.exp \ @@ -1104,6 +1148,7 @@ DISTCLEANFILES = \ chacha20.res \ codecs.res \ codecs2.res \ + codecs3.res \ core_ed25519.res \ core_keccak1600.res \ core_ristretto255.res \ @@ -1120,11 +1165,17 @@ DISTCLEANFILES = \ hash.res \ hash2.res \ hash3.res \ + hash_sha3256.res \ + hash_sha3512.res \ ipcrypt.res \ kdf.res \ kdf_hkdf.res \ kdf_hkdf2.res \ kdf_hkdf3.res \ + kdf_hkdf4.res \ + kem.res \ + kem_mlkem768.res \ + kem_xwing.res \ keygen.res \ kx.res \ metamorphic.res \ @@ -1134,6 +1185,7 @@ DISTCLEANFILES = \ onetimeauth7.res \ pwhash_argon2i.res \ pwhash_argon2id.res \ + pwhash_argon2id2.res \ pwhash_scrypt.res \ pwhash_scrypt_ll.res \ randombytes.res \ @@ -1159,12 +1211,14 @@ DISTCLEANFILES = \ sodium_utils.res \ sodium_utils2.res \ sodium_utils3.res \ + sodium_utils4.res \ sodium_version.res \ stream.res \ stream2.res \ stream3.res \ stream4.res \ stream5.res \ + stream6.res \ verify1.res \ xchacha20.res \ xof_shake128.res \ @@ -1186,13 +1240,14 @@ TESTS_TARGETS = aead_aegis128l aead_aegis256 aead_aes256gcm \ aead_aes256gcm2 aead_chacha20poly1305 aead_chacha20poly13052 \ aead_xchacha20poly1305 auth auth2 auth3 auth5 auth6 auth7 box \ box2 box7 box8 box_easy box_easy2 box_seal box_seed chacha20 \ - codecs codecs2 core_keccak1600 core1 core2 core3 core4 core5 \ - core6 ed25519_convert generichash generichash2 generichash3 \ - hash hash3 ipcrypt kdf keygen kx metamorphic misuse \ - onetimeauth onetimeauth2 onetimeauth7 pwhash_argon2i \ - pwhash_argon2id randombytes scalarmult scalarmult2 scalarmult5 \ - scalarmult6 scalarmult7 scalarmult8 secretbox secretbox2 \ - secretbox7 secretbox8 secretbox_easy secretbox_easy2 \ + codecs codecs2 codecs3 core_keccak1600 core1 core2 core3 core4 \ + core5 core6 ed25519_convert generichash generichash2 \ + generichash3 hash hash3 hash_sha3256 hash_sha3512 ipcrypt kdf \ + keygen kx metamorphic misuse onetimeauth onetimeauth2 \ + onetimeauth7 pwhash_argon2i pwhash_argon2id pwhash_argon2id2 \ + randombytes scalarmult scalarmult2 scalarmult5 scalarmult6 \ + scalarmult7 scalarmult8 secretbox secretbox2 secretbox7 \ + secretbox8 secretbox_easy secretbox_easy2 \ secretstream_xchacha20poly1305 shorthash sign sodium_core \ sodium_utils sodium_version stream stream2 stream3 stream4 \ verify1 xof_shake128 xof_shake256 xof_turboshake128 \ @@ -1248,6 +1303,8 @@ codecs_SOURCE = cmptest.h codecs.c codecs_LDADD = $(TESTS_LDADD) codecs2_SOURCE = cmptest.h codecs2.c codecs2_LDADD = $(TESTS_LDADD) +codecs3_SOURCE = cmptest.h codecs3.c +codecs3_LDADD = $(TESTS_LDADD) core_ed25519_SOURCE = cmptest.h core_ed25519.c core_ed25519_LDADD = $(TESTS_LDADD) core_keccak1600_SOURCE = cmptest.h core_keccak1600.c @@ -1278,6 +1335,10 @@ hash_SOURCE = cmptest.h hash.c hash_LDADD = $(TESTS_LDADD) hash3_SOURCE = cmptest.h hash3.c hash3_LDADD = $(TESTS_LDADD) +hash_sha3256_SOURCE = cmptest.h hash_sha3256.c +hash_sha3256_LDADD = $(TESTS_LDADD) +hash_sha3512_SOURCE = cmptest.h hash_sha3512.c +hash_sha3512_LDADD = $(TESTS_LDADD) ipcrypt_SOURCE = cmptest.h ipcrypt.c ipcrypt_LDADD = $(TESTS_LDADD) kdf_SOURCE = cmptest.h kdf.c @@ -1288,6 +1349,14 @@ kdf_hkdf2_SOURCE = cmptest.h kdf_hkdf2.c kdf_hkdf2_LDADD = $(TESTS_LDADD) kdf_hkdf3_SOURCE = cmptest.h kdf_hkdf3.c kdf_hkdf3_LDADD = $(TESTS_LDADD) +kdf_hkdf4_SOURCE = cmptest.h kdf_hkdf4.c +kdf_hkdf4_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) +kem_xwing_SOURCE = cmptest.h kem_xwing.c +kem_xwing_LDADD = $(TESTS_LDADD) keygen_SOURCE = cmptest.h keygen.c keygen_LDADD = $(TESTS_LDADD) kx_SOURCE = cmptest.h kx.c @@ -1306,6 +1375,8 @@ pwhash_argon2i_SOURCE = cmptest.h pwhash_argon2i.c pwhash_argon2i_LDADD = $(TESTS_LDADD) pwhash_argon2id_SOURCE = cmptest.h pwhash_argon2id.c pwhash_argon2id_LDADD = $(TESTS_LDADD) +pwhash_argon2id2_SOURCE = cmptest.h pwhash_argon2id2.c +pwhash_argon2id2_LDADD = $(TESTS_LDADD) pwhash_scrypt_SOURCE = cmptest.h pwhash_scrypt.c pwhash_scrypt_LDADD = $(TESTS_LDADD) pwhash_scrypt_ll_SOURCE = cmptest.h pwhash_scrypt_ll.c @@ -1356,6 +1427,8 @@ sodium_utils2_SOURCE = cmptest.h sodium_utils2.c sodium_utils2_LDADD = $(TESTS_LDADD) sodium_utils3_SOURCE = cmptest.h sodium_utils3.c sodium_utils3_LDADD = $(TESTS_LDADD) +sodium_utils4_SOURCE = cmptest.h sodium_utils4.c +sodium_utils4_LDADD = $(TESTS_LDADD) sodium_version_SOURCE = cmptest.h sodium_version.c sodium_version_LDADD = $(TESTS_LDADD) stream_SOURCE = cmptest.h stream.c @@ -1368,6 +1441,8 @@ stream4_SOURCE = cmptest.h stream4.c stream4_LDADD = $(TESTS_LDADD) stream5_SOURCE = cmptest.h stream5.c stream5_LDADD = $(TESTS_LDADD) +stream6_SOURCE = cmptest.h stream6.c +stream6_LDADD = $(TESTS_LDADD) verify1_SOURCE = cmptest.h verify1.c verify1_LDADD = $(TESTS_LDADD) xchacha20_SOURCE = cmptest.h xchacha20.c @@ -1517,6 +1592,10 @@ codecs2$(EXEEXT): $(codecs2_OBJECTS) $(codecs2_DEPENDENCIES) $(EXTRA_codecs2_DEP @rm -f codecs2$(EXEEXT) $(AM_V_CCLD)$(LINK) $(codecs2_OBJECTS) $(codecs2_LDADD) $(LIBS) +codecs3$(EXEEXT): $(codecs3_OBJECTS) $(codecs3_DEPENDENCIES) $(EXTRA_codecs3_DEPENDENCIES) + @rm -f codecs3$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(codecs3_OBJECTS) $(codecs3_LDADD) $(LIBS) + core1$(EXEEXT): $(core1_OBJECTS) $(core1_DEPENDENCIES) $(EXTRA_core1_DEPENDENCIES) @rm -f core1$(EXEEXT) $(AM_V_CCLD)$(LINK) $(core1_OBJECTS) $(core1_LDADD) $(LIBS) @@ -1577,6 +1656,14 @@ hash3$(EXEEXT): $(hash3_OBJECTS) $(hash3_DEPENDENCIES) $(EXTRA_hash3_DEPENDENCIE @rm -f hash3$(EXEEXT) $(AM_V_CCLD)$(LINK) $(hash3_OBJECTS) $(hash3_LDADD) $(LIBS) +hash_sha3256$(EXEEXT): $(hash_sha3256_OBJECTS) $(hash_sha3256_DEPENDENCIES) $(EXTRA_hash_sha3256_DEPENDENCIES) + @rm -f hash_sha3256$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(hash_sha3256_OBJECTS) $(hash_sha3256_LDADD) $(LIBS) + +hash_sha3512$(EXEEXT): $(hash_sha3512_OBJECTS) $(hash_sha3512_DEPENDENCIES) $(EXTRA_hash_sha3512_DEPENDENCIES) + @rm -f hash_sha3512$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(hash_sha3512_OBJECTS) $(hash_sha3512_LDADD) $(LIBS) + ipcrypt$(EXEEXT): $(ipcrypt_OBJECTS) $(ipcrypt_DEPENDENCIES) $(EXTRA_ipcrypt_DEPENDENCIES) @rm -f ipcrypt$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ipcrypt_OBJECTS) $(ipcrypt_LDADD) $(LIBS) @@ -1597,6 +1684,10 @@ kdf_hkdf3$(EXEEXT): $(kdf_hkdf3_OBJECTS) $(kdf_hkdf3_DEPENDENCIES) $(EXTRA_kdf_h @rm -f kdf_hkdf3$(EXEEXT) $(AM_V_CCLD)$(LINK) $(kdf_hkdf3_OBJECTS) $(kdf_hkdf3_LDADD) $(LIBS) +kdf_hkdf4$(EXEEXT): $(kdf_hkdf4_OBJECTS) $(kdf_hkdf4_DEPENDENCIES) $(EXTRA_kdf_hkdf4_DEPENDENCIES) + @rm -f kdf_hkdf4$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kdf_hkdf4_OBJECTS) $(kdf_hkdf4_LDADD) $(LIBS) + keygen$(EXEEXT): $(keygen_OBJECTS) $(keygen_DEPENDENCIES) $(EXTRA_keygen_DEPENDENCIES) @rm -f keygen$(EXEEXT) $(AM_V_CCLD)$(LINK) $(keygen_OBJECTS) $(keygen_LDADD) $(LIBS) @@ -1633,6 +1724,10 @@ pwhash_argon2id$(EXEEXT): $(pwhash_argon2id_OBJECTS) $(pwhash_argon2id_DEPENDENC @rm -f pwhash_argon2id$(EXEEXT) $(AM_V_CCLD)$(LINK) $(pwhash_argon2id_OBJECTS) $(pwhash_argon2id_LDADD) $(LIBS) +pwhash_argon2id2$(EXEEXT): $(pwhash_argon2id2_OBJECTS) $(pwhash_argon2id2_DEPENDENCIES) $(EXTRA_pwhash_argon2id2_DEPENDENCIES) + @rm -f pwhash_argon2id2$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pwhash_argon2id2_OBJECTS) $(pwhash_argon2id2_LDADD) $(LIBS) + pwhash_scrypt$(EXEEXT): $(pwhash_scrypt_OBJECTS) $(pwhash_scrypt_DEPENDENCIES) $(EXTRA_pwhash_scrypt_DEPENDENCIES) @rm -f pwhash_scrypt$(EXEEXT) $(AM_V_CCLD)$(LINK) $(pwhash_scrypt_OBJECTS) $(pwhash_scrypt_LDADD) $(LIBS) @@ -1733,6 +1828,10 @@ sodium_utils3$(EXEEXT): $(sodium_utils3_OBJECTS) $(sodium_utils3_DEPENDENCIES) $ @rm -f sodium_utils3$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sodium_utils3_OBJECTS) $(sodium_utils3_LDADD) $(LIBS) +sodium_utils4$(EXEEXT): $(sodium_utils4_OBJECTS) $(sodium_utils4_DEPENDENCIES) $(EXTRA_sodium_utils4_DEPENDENCIES) + @rm -f sodium_utils4$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(sodium_utils4_OBJECTS) $(sodium_utils4_LDADD) $(LIBS) + sodium_version$(EXEEXT): $(sodium_version_OBJECTS) $(sodium_version_DEPENDENCIES) $(EXTRA_sodium_version_DEPENDENCIES) @rm -f sodium_version$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sodium_version_OBJECTS) $(sodium_version_LDADD) $(LIBS) @@ -1757,6 +1856,10 @@ stream5$(EXEEXT): $(stream5_OBJECTS) $(stream5_DEPENDENCIES) $(EXTRA_stream5_DEP @rm -f stream5$(EXEEXT) $(AM_V_CCLD)$(LINK) $(stream5_OBJECTS) $(stream5_LDADD) $(LIBS) +stream6$(EXEEXT): $(stream6_OBJECTS) $(stream6_DEPENDENCIES) $(EXTRA_stream6_DEPENDENCIES) + @rm -f stream6$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(stream6_OBJECTS) $(stream6_LDADD) $(LIBS) + verify1$(EXEEXT): $(verify1_OBJECTS) $(verify1_DEPENDENCIES) $(EXTRA_verify1_DEPENDENCIES) @rm -f verify1$(EXEEXT) $(AM_V_CCLD)$(LINK) $(verify1_OBJECTS) $(verify1_LDADD) $(LIBS) @@ -1815,6 +1918,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chacha20.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/codecs.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/codecs2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/codecs3.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core1.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core3.Po@am__quote@ # am--include-marker @@ -1830,11 +1934,14 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generichash3.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash3.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_sha3256.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_sha3512.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipcrypt.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdf.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdf_hkdf.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdf_hkdf2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdf_hkdf3.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdf_hkdf4.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keygen.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kx.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/metamorphic.Po@am__quote@ # am--include-marker @@ -1844,6 +1951,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onetimeauth7.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pwhash_argon2i.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pwhash_argon2id.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pwhash_argon2id2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pwhash_scrypt.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pwhash_scrypt_ll.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/randombytes.Po@am__quote@ # am--include-marker @@ -1869,12 +1977,14 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sodium_utils.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sodium_utils2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sodium_utils3.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sodium_utils4.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sodium_version.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream3.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream4.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream5.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream6.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify1.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xchacha20.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xof2.Po@am__quote@ # am--include-marker @@ -2305,6 +2415,13 @@ codecs2.log: codecs2$(EXEEXT) --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +codecs3.log: codecs3$(EXEEXT) + @p='codecs3$(EXEEXT)'; \ + b='codecs3'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) core_keccak1600.log: core_keccak1600$(EXEEXT) @p='core_keccak1600$(EXEEXT)'; \ b='core_keccak1600'; \ @@ -2396,6 +2513,20 @@ hash3.log: hash3$(EXEEXT) --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +hash_sha3256.log: hash_sha3256$(EXEEXT) + @p='hash_sha3256$(EXEEXT)'; \ + b='hash_sha3256'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +hash_sha3512.log: hash_sha3512$(EXEEXT) + @p='hash_sha3512$(EXEEXT)'; \ + b='hash_sha3512'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) ipcrypt.log: ipcrypt$(EXEEXT) @p='ipcrypt$(EXEEXT)'; \ b='ipcrypt'; \ @@ -2473,6 +2604,13 @@ pwhash_argon2id.log: pwhash_argon2id$(EXEEXT) --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +pwhash_argon2id2.log: pwhash_argon2id2$(EXEEXT) + @p='pwhash_argon2id2$(EXEEXT)'; \ + b='pwhash_argon2id2'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) randombytes.log: randombytes$(EXEEXT) @p='randombytes$(EXEEXT)'; \ b='randombytes'; \ @@ -2690,6 +2828,13 @@ sodium_utils3.log: sodium_utils3$(EXEEXT) --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +sodium_utils4.log: sodium_utils4$(EXEEXT) + @p='sodium_utils4$(EXEEXT)'; \ + b='sodium_utils4'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) core_ed25519.log: core_ed25519$(EXEEXT) @p='core_ed25519$(EXEEXT)'; \ b='core_ed25519'; \ @@ -2725,6 +2870,13 @@ kdf_hkdf3.log: kdf_hkdf3$(EXEEXT) --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +kdf_hkdf4.log: kdf_hkdf4$(EXEEXT) + @p='kdf_hkdf4$(EXEEXT)'; \ + b='kdf_hkdf4'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) pwhash_scrypt.log: pwhash_scrypt$(EXEEXT) @p='pwhash_scrypt$(EXEEXT)'; \ b='pwhash_scrypt'; \ @@ -2739,6 +2891,13 @@ stream5.log: stream5$(EXEEXT) --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +stream6.log: stream6$(EXEEXT) + @p='stream6$(EXEEXT)'; \ + b='stream6'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) pwhash_scrypt_ll.log: pwhash_scrypt_ll$(EXEEXT) @p='pwhash_scrypt_ll$(EXEEXT)'; \ b='pwhash_scrypt_ll'; \ @@ -2892,6 +3051,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/chacha20.Po -rm -f ./$(DEPDIR)/codecs.Po -rm -f ./$(DEPDIR)/codecs2.Po + -rm -f ./$(DEPDIR)/codecs3.Po -rm -f ./$(DEPDIR)/core1.Po -rm -f ./$(DEPDIR)/core2.Po -rm -f ./$(DEPDIR)/core3.Po @@ -2907,11 +3067,14 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/generichash3.Po -rm -f ./$(DEPDIR)/hash.Po -rm -f ./$(DEPDIR)/hash3.Po + -rm -f ./$(DEPDIR)/hash_sha3256.Po + -rm -f ./$(DEPDIR)/hash_sha3512.Po -rm -f ./$(DEPDIR)/ipcrypt.Po -rm -f ./$(DEPDIR)/kdf.Po -rm -f ./$(DEPDIR)/kdf_hkdf.Po -rm -f ./$(DEPDIR)/kdf_hkdf2.Po -rm -f ./$(DEPDIR)/kdf_hkdf3.Po + -rm -f ./$(DEPDIR)/kdf_hkdf4.Po -rm -f ./$(DEPDIR)/keygen.Po -rm -f ./$(DEPDIR)/kx.Po -rm -f ./$(DEPDIR)/metamorphic.Po @@ -2921,6 +3084,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/onetimeauth7.Po -rm -f ./$(DEPDIR)/pwhash_argon2i.Po -rm -f ./$(DEPDIR)/pwhash_argon2id.Po + -rm -f ./$(DEPDIR)/pwhash_argon2id2.Po -rm -f ./$(DEPDIR)/pwhash_scrypt.Po -rm -f ./$(DEPDIR)/pwhash_scrypt_ll.Po -rm -f ./$(DEPDIR)/randombytes.Po @@ -2946,12 +3110,14 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/sodium_utils.Po -rm -f ./$(DEPDIR)/sodium_utils2.Po -rm -f ./$(DEPDIR)/sodium_utils3.Po + -rm -f ./$(DEPDIR)/sodium_utils4.Po -rm -f ./$(DEPDIR)/sodium_version.Po -rm -f ./$(DEPDIR)/stream.Po -rm -f ./$(DEPDIR)/stream2.Po -rm -f ./$(DEPDIR)/stream3.Po -rm -f ./$(DEPDIR)/stream4.Po -rm -f ./$(DEPDIR)/stream5.Po + -rm -f ./$(DEPDIR)/stream6.Po -rm -f ./$(DEPDIR)/verify1.Po -rm -f ./$(DEPDIR)/xchacha20.Po -rm -f ./$(DEPDIR)/xof2.Po @@ -3028,6 +3194,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/chacha20.Po -rm -f ./$(DEPDIR)/codecs.Po -rm -f ./$(DEPDIR)/codecs2.Po + -rm -f ./$(DEPDIR)/codecs3.Po -rm -f ./$(DEPDIR)/core1.Po -rm -f ./$(DEPDIR)/core2.Po -rm -f ./$(DEPDIR)/core3.Po @@ -3043,11 +3210,14 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/generichash3.Po -rm -f ./$(DEPDIR)/hash.Po -rm -f ./$(DEPDIR)/hash3.Po + -rm -f ./$(DEPDIR)/hash_sha3256.Po + -rm -f ./$(DEPDIR)/hash_sha3512.Po -rm -f ./$(DEPDIR)/ipcrypt.Po -rm -f ./$(DEPDIR)/kdf.Po -rm -f ./$(DEPDIR)/kdf_hkdf.Po -rm -f ./$(DEPDIR)/kdf_hkdf2.Po -rm -f ./$(DEPDIR)/kdf_hkdf3.Po + -rm -f ./$(DEPDIR)/kdf_hkdf4.Po -rm -f ./$(DEPDIR)/keygen.Po -rm -f ./$(DEPDIR)/kx.Po -rm -f ./$(DEPDIR)/metamorphic.Po @@ -3057,6 +3227,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/onetimeauth7.Po -rm -f ./$(DEPDIR)/pwhash_argon2i.Po -rm -f ./$(DEPDIR)/pwhash_argon2id.Po + -rm -f ./$(DEPDIR)/pwhash_argon2id2.Po -rm -f ./$(DEPDIR)/pwhash_scrypt.Po -rm -f ./$(DEPDIR)/pwhash_scrypt_ll.Po -rm -f ./$(DEPDIR)/randombytes.Po @@ -3082,12 +3253,14 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/sodium_utils.Po -rm -f ./$(DEPDIR)/sodium_utils2.Po -rm -f ./$(DEPDIR)/sodium_utils3.Po + -rm -f ./$(DEPDIR)/sodium_utils4.Po -rm -f ./$(DEPDIR)/sodium_version.Po -rm -f ./$(DEPDIR)/stream.Po -rm -f ./$(DEPDIR)/stream2.Po -rm -f ./$(DEPDIR)/stream3.Po -rm -f ./$(DEPDIR)/stream4.Po -rm -f ./$(DEPDIR)/stream5.Po + -rm -f ./$(DEPDIR)/stream6.Po -rm -f ./$(DEPDIR)/verify1.Po -rm -f ./$(DEPDIR)/xchacha20.Po -rm -f ./$(DEPDIR)/xof2.Po diff --git a/test/default/kem_mlkem768.c b/test/default/kem_mlkem768.c new file mode 100644 index 00000000..d411c10d --- /dev/null +++ b/test/default/kem_mlkem768.c @@ -0,0 +1,365 @@ +#define TEST_NAME "kem_mlkem768" +#include "cmptest.h" + +static const char tv1_d[] = + "7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d"; +static const char tv1_z[] = + "b505d7cfad1b497499323c8686325e4792f267aafa3f87ca60d01cb54f29202a"; +static const char tv1_pk_prefix[] = + "a8e651a1e685f22478a8954f007bc7711b930772c78f092e82878e3e937f3679"; +static const char tv1_m[] = + "eb4a7c66ef4eba2ddb38c88d8bc706b1d639002198172a7b1942eca8f6c001ba"; +static const char tv1_ct_prefix[] = + "3b835a5fa145387a0819c4daa1e65fbe2ba5400afcd640bbddbbe3585f24bedd"; +static const char tv1_ss[] = + "ac865f839fef1bf3d528dd7504bed2f64b5502b0fa81d1c32763658e4aac5037"; + +static const char tv2_d[] = + "d60b93492a1d8c1c7ba6fc0b733137f3406cee8110a93f170e7a78658af326d9"; +static const char tv2_z[] = + "588522d326e7f105f11c4e8d97e119e193af42dc28409f4f7572ada538b52c1f"; +static const char tv2_pk_prefix[] = + "93c140f6c47b7e53b96f72bb18447d277cc021c144a0f7a35e30b57386a78ac9"; +static const char tv2_m[] = + "46401015603c5e2174cb94ac742e836b516e2d570f15de0b9d0204d79ac64ba3"; +static const char tv2_ct_prefix[] = + "4ddf4e2919943817ab3b4cb085daefe5fec774d83d96c2cee74149e25addd15f"; +static const char tv2_ss[] = + "950492e940bfa86ac28183de02efc04017d1755106a854fbb2ac68174f705b41"; + +static const char wycheproof_seed[] = + "cbfc4405d1b2a3a386c94c25e0f2d5f5ee92cb0388ff4d6aa04223086d51c3fd" + "24752da14c9fc3b8ae0d9e4a8b1016b8d8fc69e229c03ea2ef08a4ae0cffc37f"; + +static const char wycheproof_ek[] = + "8b9a7354e8c1c17a9898f96caf99bba1c625ae0983c4d26e60c12f59bc25d756" + "182b17979e713fff129e6c336a2317770380858129cb91a902ea5455ca076c20" + "e4158f393aa2783053d8acf92c3286a10436d72af3e8903ce22f8cbab18b1309" + "aca205aa8a3da45807e5b60e6967a640a713a5b81b0d82bc406934e3c88910cc" + "06f09a68bce991009bb56ae233296218ff5baf1f475390b8b7494a4e08364598" + "5437f2495a073222fea058e1672034151a2e14c2cbcb4ad9068c8e7bcb02886c" + "4087c14bd8823ec66393fb2e12326b38e655dcab1c13cb2931358715c8be5153" + "293229cc994a5702b7295a6a4a73249ac5a30a32a6b91dca768c177d8fa59054" + "e548bee40257db6962a83b64ec6de0d3be7b1812c5d99e7a38cf54eaa8413aa0" + "bd02bf374461f29c2b6aea56f7d33e10dbbc75bb1bf6b555213aac33e652443a" + "186a618b6e9a293919693f1673ea159d0ee52c92d53e9a5cbd5f4c44419b5493" + "f0286efcb9b5a2ad56a713c4f61ed431aa987805a90475391ccd4c7a28d884bf" + "1a926b7675b9208897a89a6384c154acca3521c32a994949b2e80b2ff2518c0b" + "bd34184cda443de498a05dfba9ce701bb914179a0188be0bcda6fbc2cd93afb0" + "42481b4a84d821160a1b0ade8bcb97dbaf681547cce0bca674151a261a21aa04" + "fda318c921c38425b775b995cd7b4eb6369f0b211da186594de815fa3b53a680" + "43e1946468a5899b90578ad49397306f71acab67c258fa17a31893b72d22151c" + "e1afee150fe550bffde8a24fe4740dd43f387c7ad20b5cca5997879536c30715" + "74901147727341c1a6fc8043e6454903e88217f0c92b9a4ac54a86e790939087" + "8a35ba18c1e26b13049f41c522bc049d74db6f76caba39f23d8f07abc26a07a1" + "caba71cb5c12fbc20a715450b2228d17b2ba985cfe2496b033b55f300baf9929" + "64388a5422298f627ba567730ddb03a195806a5c23a1d315481c52814b0681ea" + "3c804b02c90688c2fbbce9b17d230a42f8b865417c9e93347f5ff624879962747c7eed886acd48a994b22064ca499c69aa4825be60260d12f63102799828b3cc" + "ebaa4340b749605017eb4598ff13a634500a48470de9078a34106267d25a0b14" + "4d8cdb1a4d527692153da013c0ab27ae2ca955e7c66238746022d50630892933" + "a05c283a9f4c00c9f984646f75471081722ed3404ce60fed4a06702b8728b62d" + "920b3224206ab0a4694f9c18e3162b529c16af04b87b4a61cd53a757906d67a1" + "39629585d423a3b0986f29c95984e2095ea4608784b0b31c20cbc36cfd60b773" + "389fe5a8c0958211a35b2c45f21f51a08693c19bfc388c2d677a214ccc5a7cb0" + "b67030fd6987503c91b0f2646985a9048489dd882bd4141f5419554eb738fa73" + "33c5c57a4ce5541fd6b8ad454c2dea67ad1c6f848c0a44a1872e40a17d987075" + "d762ba5aaa21d435dd079b989a8ee21a2ce898934a98a02d5b381c302a2d7694" + "8fa65de15666f57750d580ae1a541c700692dd0b0a6799b5cdb893413bb89bb6" + "5182f219a4bc3c80b43bb591bcd05ac6e9a366552558ed5c5fbe7b4acfc7b233" + "72094f6a87f26c0c46646c55a888871324fea7536e586a5149b9b707c86ea076" + "486a6822b9bbf59fbfcaedc13284b9813cabdd526e326a6832d3b36efc3102ef"; + +static const char wycheproof_ct[] = + "00e96c44eb5f5380d80b4cb05d608971a28fbe838b912b558bf9676c6c67c969" + "2ed6ea063fc47b70d5d6004825c269b9cb8e68b5728d67f44844d97686a11154" + "e3cbd4a6f9e47524d93d851bdce480d7762ded09be53d17cce3ee28dc5a06911" + "c062b99b218355dd5822108c55e2c67f7ea0b74b6189b33b4589d8ff9d0c867d" + "13edaaf1c5f724675320beda3e6acc673c048fa04a1b30f899227d5a555e08a4" + "12a47b7db75eb118a8844a71b186880426f6bb6e77186d18e753cbcce93c9fb7" + "6c729875b4d473eeca8dab9941969faef04df9ce3178e7341eab416d28bb7aee" + "12bfb8f4c3df814eff45a0187329079acfc41a8e8dba7b08d111f02e37a1d2b6" + "9e57eef808fcc6ae23385534a420a93dfb6a95c73e2f1016177c4fe9d3ced769" + "e277293aaceded6d07efc7890eaa885bd1e73f9e5da2b9cfda0d44cbc9090705" + "ac2ce3e7bcd7775b593c706e45ddc97d3a65d9b7e73673f9473df5bfec689671" + "f73e7f6ee77c730a8ebda1f0b2c112a71904d6f28a51d8d479f8323fb485e722" + "f5c4d5857e95989a9cbaf273efd04fc3cbde98baa9969e095e88accecfbd12ef" + "2155497a5b15fe91a70d1106b91a568363bfc2d6736cc8138cbc41ddf1e54fd4" + "0511e27d89e2c26c027b63c156e2bbb998faaed3d72186f0cc626dad39a782dc" + "da2087fd13a9498e10b41b685646a227ea1166a5632c195983f4aba2b718b407" + "4030d57126d34c38349892007acbea9e393b967dc3146b270f080a1f0bee90d6" + "5a095a6352a7718ed1717a8025a2bd38c66d120baf4247676a1fe044a57ce268" + "c078f8ff46cc26fe4f9c7a03d6467adacb8418d26273662bce1f7bc00b906e00" + "88e95dc0fb419e2232e85aac77b9e7cd563e604de5e1d3e9693dcd3b19865cf4" + "250773691e7e0af9c2755cd31f49d1f96708f3ba2f0b98184525abb869e12d5c" + "ea0ac1740181a875035300b05a54b8d42ee3b4ae92b06e43cd807e2b096c977f" + "23c61ef8c989c52ed83754076dea1323f639250bef61bdf903bf7961cec89ba6" + "942d9d0647ac9c8195d93ed8abcedf25754644035719a5a0a1c8c0798912726a" + "9a8258e4c10ae7485322ed9ba331f6f090c4b492a4fcf53d753cd34f28ec0443" + "fce0724f43c89a3942169d5099a8f7430f38691ebce2e3fe4f600d82c7ccedf6" + "0673f8e5d4c1a9f84b8b5b23f5ed63defb6a7205e0a8b105bdc6ff4568fc78cb" + "4456b02fedb7f4c48f6fd6b69216a3319821039db40e19a31a0b0c9d471d5a7a" + "73865d26f8be3595525b1ec4a8579efd07ea98e2602e2bffdfd8febc5c7b4c73" + "6d326b5030ccc6faf9420a9c156a8f4516b9fff675459dfdcd4ef85d7adbdffd" + "60f4a39628e399cc752c2e99ab2f431dc765e7c9d206bfe32649fbef4ef48b1d" + "7936fc74766d724350ee2245a8d5f23fbc6c7ed8b57168ce1e864e49d7f8c475" + "dcda140bd42473825b3c72eb8c54780188813011e1962a503f9b516e13226de6" + "375b204733b0192183c8f55e870e61cf8947c3191790bc0b657bc43aebc9d86c"; + +static const char wycheproof_ss[] = + "76c10bb1d86d96d7eb18e298363e51f7728e113f455df7d15017940ed3541451"; + +static const char *wycheproof_invalid_ek[] = { + "016d4cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d2f2bbe896a8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4ff8657da81d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d15837bade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", + "8b654cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d212d0e896a8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4ff8657da81d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d15837bade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", + "ff6f4cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d2f2bbe896a8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4ff8657da81d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d15837bade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", + "8b654cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d2f2ffe896a8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4ff8657da81d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d15837bade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", + "8b654cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d2f2bb019da8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4ff8657da81d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d15837bade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", + "8b654cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d2f2bbe896a8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4f18d07da81d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d15837bade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", + "8b654cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d2f2bbff9fa8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4ff8657da81d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d15837bade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", + "8b654cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d2f2bbe896a8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4ff8ff7da81d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d15837bade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", + "8b654cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d2f2bbe896a8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4ff86501ad1d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d15837bade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", + "8b654cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d2f2bbe896a8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4ff8657da81d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d1513d0ade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", + "8b654cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d2f2bbe896a8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4ff8657da81d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d15f3ffade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", + "8b654cd2120d97581838192bb56463ee2b9a96e620bc7976bf3634f441ab0641ba3a904cfd4b55ba40cc6fdb906ac1a95637112c7a48dbf311d67004bb583e068b9936b32463245da31685a878a90d205162b587a322cebe475fc70186b8b52cab2c9e838873406a98574c65e83b0063d316a8654b5ef7537b487a25114c521bbfdb4780d58804c1c172cfac59b9bb8ba804a10fc6607633cc89d18bc5579d7a0825a2a72bc32869ba8518fafa522a9950ef7ab4625c417e6b6fa3f0165dd47d78ab8587f22b99abad73a90880b2b08c4876b61ca536f675b4b8a37460ad4400910d265e5146ae4be61a09c30a1de01f4636a802413fc8f051cde78e4fc51ba8f3a2cad1474775a7d7ec513a57541861702d6480c70cce8912bd2c01bf11378604005695d64c1969cf25714ae287c019da020d66af70c1528e12365fe25106e8179b04ccf0cba724fb6a89b83ca9f55012b66267337f6618484a7a70e8a1163cb17426ea132e1a56e53ab86e491e39dbbe4e4465a785106b5255dc2190d2f2bbe896a8cc64a228c2b9a8943214f97a3b40a8e41053fd4346a7fcab06fa72de8c33cca788e2e09e09dacd7034038ec13d1a065cf7d14c5de44a6d56873232ba84585b9d0811320659be5a19cdc759969a0bdeca5410977e40163dc2da6665c45954b900e3a97512897d1c7a6cc2a60acfb2175151043ae29a0d240e760c1d100a6877b5a10fb69054d0cf80dca4c15350fc685001899a7a6515e9c7ac3325938997b4387c16022a91ee5c2fa2ab8bd6fa898667831af38349fb1badb52b472210e36bca63342a0cd869a44a04a7e68859f66094d8c104c33b38444b8fb168025b479a5a7772c1bacd73b3ef88ae6fe66aab1846723c65d3d106c1722e2235ac7865a04584324062826e463edc13803c9796e54bce6b80933057abb9328ab501688e69148fbaa811ea9792316068a9abfa583e45ab6549ccb7e9e70d9139c0ebc7b995ec1463fc321f38bff2b2b995192eaa305daf1c44352371089637ed673dd82b8ad8bb3bb2299b9e5369f104a454357e5a2238e6315fa720343064be4ff865ffaf1d7c5c4b51c5b896669f029483f7c273f763ce26150ce3550c4ddcb26f37b2dea19b2dd197d449c9b693c10a3cb04de8c9f425a523d173240a69c4f0479bc177d836cda34b2cb64440acd464d904b66662295f0950460b710f089090b49fc7a6276e219eb4f19ee4dc12d2045141497064c4beae80a8ded00438d90a012963de54380f137666b2ab09844198ba807a4972f1b35f7b9789d847cc3e5a4a08cb17d4d9065ce09a74609ae935218c5bcd51f9bd774aa720e6423f75a974a3c21835a6018886dd119766909413aa576144c10b49c17ba1c793f78f7c580eba195bd8407f00f568c4d546c7d677dd02c78930c3e969b5584129e1815c6ce32162f09d6f7303f69c5f0216625c782666f9c8cf8678f1b63635067392aa3fba56204a1831491c2eee759ce674abd34251732949f9874059b35b66089a1905896c94111511a449f695e2c036d87b585a74834d676b9a2b2aa74a386cfa446f86934b844068147013396fa2d3bb8fa11d97b992a04a6ba65c189b238106cb8d15837bade3c278034d6d86bd50a3049feb37499b08aba61b38ffeaf94bc84cdb360fbc", +}; + +static int +test_kat_vector(const char *d_hex, const char *z_hex, const char *pk_prefix_hex, + const char *m_hex, const char *ct_prefix_hex, const char *ss_hex) +{ + unsigned char seed[crypto_kem_mlkem768_SEEDBYTES]; + unsigned char pk[crypto_kem_mlkem768_PUBLICKEYBYTES]; + unsigned char sk[crypto_kem_mlkem768_SECRETKEYBYTES]; + unsigned char enc_seed[32]; + unsigned char ct[crypto_kem_mlkem768_CIPHERTEXTBYTES]; + unsigned char ss_enc[crypto_kem_mlkem768_SHAREDSECRETBYTES]; + unsigned char ss_dec[crypto_kem_mlkem768_SHAREDSECRETBYTES]; + unsigned char expected_pk_prefix[32]; + unsigned char expected_ct_prefix[32]; + unsigned char expected_ss[32]; + char hex[65]; + + sodium_hex2bin(seed, 32, d_hex, 64, NULL, NULL, NULL); + sodium_hex2bin(seed + 32, 32, z_hex, 64, NULL, NULL, NULL); + sodium_hex2bin(enc_seed, 32, m_hex, 64, NULL, NULL, NULL); + sodium_hex2bin(expected_pk_prefix, 32, pk_prefix_hex, 64, NULL, NULL, NULL); + sodium_hex2bin(expected_ct_prefix, 32, ct_prefix_hex, 64, NULL, NULL, NULL); + sodium_hex2bin(expected_ss, 32, ss_hex, 64, NULL, NULL, NULL); + + crypto_kem_mlkem768_seed_keypair(pk, sk, seed); + + if (memcmp(pk, expected_pk_prefix, 32) != 0) { + sodium_bin2hex(hex, sizeof hex, pk, 32); + printf("pk mismatch: got %s\n", hex); + return -1; + } + + assert(crypto_kem_mlkem768_enc_deterministic(ct, ss_enc, pk, enc_seed) == 0); + + if (memcmp(ct, expected_ct_prefix, 32) != 0) { + sodium_bin2hex(hex, sizeof hex, ct, 32); + 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_mlkem768_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_mlkem768(void) +{ + unsigned char *pk; + unsigned char *sk; + unsigned char *seed; + unsigned char *ct; + unsigned char *ss_enc; + unsigned char *ss_dec; + unsigned char *enc_seed; + char hex[65]; + int i; + + pk = (unsigned char *) sodium_malloc(crypto_kem_mlkem768_PUBLICKEYBYTES); + sk = (unsigned char *) sodium_malloc(crypto_kem_mlkem768_SECRETKEYBYTES); + seed = (unsigned char *) sodium_malloc(crypto_kem_mlkem768_SEEDBYTES); + ct = (unsigned char *) sodium_malloc(crypto_kem_mlkem768_CIPHERTEXTBYTES); + ss_enc = (unsigned char *) sodium_malloc(crypto_kem_mlkem768_SHAREDSECRETBYTES); + ss_dec = (unsigned char *) sodium_malloc(crypto_kem_mlkem768_SHAREDSECRETBYTES); + enc_seed = (unsigned char *) sodium_malloc(32); + + for (i = 0; i < (int) crypto_kem_mlkem768_SEEDBYTES; i++) { + seed[i] = (unsigned char) i; + } + crypto_kem_mlkem768_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 (first 32 bytes): [%s]\n", hex); + + for (i = 0; i < 32; i++) { + enc_seed[i] = (unsigned char)(i + 64); + } + assert(crypto_kem_mlkem768_enc_deterministic(ct, ss_enc, pk, enc_seed) == 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_mlkem768_SHAREDSECRETBYTES); + printf("ss_enc: [%s]\n", hex); + + assert(crypto_kem_mlkem768_dec(ss_dec, ct, sk) == 0); + + sodium_bin2hex(hex, sizeof hex, ss_dec, crypto_kem_mlkem768_SHAREDSECRETBYTES); + printf("ss_dec: [%s]\n", hex); + + if (memcmp(ss_enc, ss_dec, crypto_kem_mlkem768_SHAREDSECRETBYTES) != 0) { + printf("ERROR: shared secrets don't match!\n"); + } else { + printf("shared secrets match: ok\n"); + } + + crypto_kem_mlkem768_keypair(pk, sk); + assert(crypto_kem_mlkem768_enc(ct, ss_enc, pk) == 0); + assert(crypto_kem_mlkem768_dec(ss_dec, ct, sk) == 0); + if (memcmp(ss_enc, ss_dec, crypto_kem_mlkem768_SHAREDSECRETBYTES) != 0) { + printf("ERROR: shared secrets don't match (random keys)!\n"); + } else { + printf("random keypair test: ok\n"); + } + + ct[0] ^= 0x01; + assert(crypto_kem_mlkem768_dec(ss_dec, ct, sk) == 0); + if (memcmp(ss_enc, ss_dec, crypto_kem_mlkem768_SHAREDSECRETBYTES) == 0) { + printf("ERROR: decapsulation succeeded with modified ciphertext!\n"); + } else { + printf("modified ciphertext rejected: ok\n"); + } + + assert(crypto_kem_mlkem768_publickeybytes() == crypto_kem_mlkem768_PUBLICKEYBYTES); + assert(crypto_kem_mlkem768_secretkeybytes() == crypto_kem_mlkem768_SECRETKEYBYTES); + assert(crypto_kem_mlkem768_ciphertextbytes() == crypto_kem_mlkem768_CIPHERTEXTBYTES); + assert(crypto_kem_mlkem768_sharedsecretbytes() == crypto_kem_mlkem768_SHAREDSECRETBYTES); + assert(crypto_kem_mlkem768_seedbytes() == crypto_kem_mlkem768_SEEDBYTES); + + assert(crypto_kem_mlkem768_PUBLICKEYBYTES == 1184U); + assert(crypto_kem_mlkem768_SECRETKEYBYTES == 2400U); + assert(crypto_kem_mlkem768_CIPHERTEXTBYTES == 1088U); + assert(crypto_kem_mlkem768_SHAREDSECRETBYTES == 32U); + assert(crypto_kem_mlkem768_SEEDBYTES == 64U); + + printf("constants: ok\n"); + + sodium_free(enc_seed); + sodium_free(ss_dec); + sodium_free(ss_enc); + sodium_free(ct); + sodium_free(seed); + sodium_free(sk); + sodium_free(pk); + + printf("tv_kem_mlkem768: ok\n"); +} + +static void +tv_kem_mlkem768_kat(void) +{ + printf("NIST KAT vector 1: "); + if (test_kat_vector(tv1_d, tv1_z, tv1_pk_prefix, tv1_m, tv1_ct_prefix, tv1_ss) == 0) { + printf("ok\n"); + } else { + printf("FAILED\n"); + } + + printf("NIST KAT vector 2: "); + if (test_kat_vector(tv2_d, tv2_z, tv2_pk_prefix, tv2_m, tv2_ct_prefix, tv2_ss) == 0) { + printf("ok\n"); + } else { + printf("FAILED\n"); + } +} + +static void +tv_wycheproof_decapsulation(void) +{ + unsigned char seed[64]; + unsigned char pk[crypto_kem_mlkem768_PUBLICKEYBYTES]; + unsigned char sk[crypto_kem_mlkem768_SECRETKEYBYTES]; + unsigned char ct[crypto_kem_mlkem768_CIPHERTEXTBYTES]; + unsigned char ss[crypto_kem_mlkem768_SHAREDSECRETBYTES]; + unsigned char expected_ek[crypto_kem_mlkem768_PUBLICKEYBYTES]; + unsigned char expected_ss[32]; + + sodium_hex2bin(seed, sizeof seed, wycheproof_seed, strlen(wycheproof_seed), + NULL, NULL, NULL); + sodium_hex2bin(ct, sizeof ct, wycheproof_ct, strlen(wycheproof_ct), + NULL, NULL, NULL); + sodium_hex2bin(expected_ek, sizeof expected_ek, wycheproof_ek, strlen(wycheproof_ek), + NULL, NULL, NULL); + sodium_hex2bin(expected_ss, sizeof expected_ss, wycheproof_ss, strlen(wycheproof_ss), + NULL, NULL, NULL); + + crypto_kem_mlkem768_seed_keypair(pk, sk, seed); + + printf("Wycheproof decapsulation (tcId 1): "); + if (memcmp(pk, expected_ek, crypto_kem_mlkem768_PUBLICKEYBYTES) != 0) { + printf("FAILED (pk mismatch)\n"); + return; + } + + assert(crypto_kem_mlkem768_dec(ss, ct, sk) == 0); + + if (memcmp(ss, expected_ss, 32) == 0) { + printf("ok\n"); + } else { + printf("FAILED (ss mismatch)\n"); + } +} + +static void +tv_wycheproof_modulus_overflow(void) +{ + unsigned char ek[crypto_kem_mlkem768_PUBLICKEYBYTES]; + unsigned char ct[crypto_kem_mlkem768_CIPHERTEXTBYTES]; + unsigned char ss[crypto_kem_mlkem768_SHAREDSECRETBYTES]; + unsigned char m[32]; + size_t i; + int ret; + + memset(m, 0x42, 32); + + printf("Wycheproof modulus overflow: "); + for (i = 0; i < sizeof wycheproof_invalid_ek / sizeof wycheproof_invalid_ek[0]; i++) { + sodium_hex2bin(ek, sizeof ek, wycheproof_invalid_ek[i], + strlen(wycheproof_invalid_ek[i]), NULL, NULL, NULL); + ret = crypto_kem_mlkem768_enc_deterministic(ct, ss, ek, m); + if (ret != 0) { + printf("ok (rejected invalid ek)\n"); + return; + } + } + printf("accepted (no validation)\n"); +} + +int +main(void) +{ + tv_kem_mlkem768(); + tv_kem_mlkem768_kat(); + tv_wycheproof_decapsulation(); + tv_wycheproof_modulus_overflow(); + + return 0; +} diff --git a/test/default/kem_mlkem768.exp b/test/default/kem_mlkem768.exp new file mode 100644 index 00000000..e983d334 --- /dev/null +++ b/test/default/kem_mlkem768.exp @@ -0,0 +1,14 @@ +pk (first 32 bytes): [298aa10d423c8dda069d02bc59e6cdf03a096b8b3da4cab9b80ca4a14907672c] +sk (first 32 bytes): [27d2a77f33756f61208ef113abe82595873d4abc730e5b5d679529bf6a4ceb63] +ct (first 32 bytes): [695a60d9c79f08343ed9ff5802582063c2ca3a648e543d924affbb39ef4de656] +ss_enc: [9cddd089ffe70e3996e76f7c8d06746df34d07e8657bc0fcf2bb0e1c3084aea1] +ss_dec: [9cddd089ffe70e3996e76f7c8d06746df34d07e8657bc0fcf2bb0e1c3084aea1] +shared secrets match: ok +random keypair test: ok +modified ciphertext rejected: ok +constants: ok +tv_kem_mlkem768: ok +NIST KAT vector 1: ok +NIST KAT vector 2: ok +Wycheproof decapsulation (tcId 1): ok +Wycheproof modulus overflow: ok (rejected invalid ek)