From glin at suse.com Tue Sep 2 09:14:27 2025 From: glin at suse.com (Gary Lin) Date: Tue, 2 Sep 2025 15:14:27 +0800 Subject: [PATCH] kdf: Avoid redundant memcpy() Message-ID: <20250902071427.1781-1-glin@suse.com> * cipher/kdf.c (fill_block): Xor 'ref_block' and 'prev_block' directly to avoid a redundant memcpy(). Signed-off-by: Gary Lin --- cipher/kdf.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cipher/kdf.c b/cipher/kdf.c index 71156ea4..16cec4e4 100644 --- a/cipher/kdf.c +++ b/cipher/kdf.c @@ -588,9 +588,14 @@ fill_block (const u64 *prev_block, const u64 *ref_block, u64 *curr_block, u64 block_tmp[ARGON2_WORDS_IN_BLOCK]; int i; - memcpy (block_r, ref_block, 1024); if (prev_block) - xor_block (block_r, prev_block); + { + for (i = 0; i < ARGON2_WORDS_IN_BLOCK; i++) + block_r[i] = ref_block[i] ^ prev_block[i]; + } + else + memcpy (block_r, ref_block, 1024); + memcpy (block_tmp, block_r, 1024); if (with_xor) -- 2.51.0 From jussi.kivilinna at iki.fi Wed Sep 17 17:38:02 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 17 Sep 2025 18:38:02 +0300 Subject: [PATCH] hwfeature: fix "riscv-zvkg" HW feature mapping Message-ID: <20250917153802.315674-1-jussi.kivilinna@iki.fi> * src/hwfeatures.c (hwflist) [HAVE_CPU_ARCH_RISCV]: Fix mapping from ZVKNED to ZVKG for "riscv-zvkg". -- Signed-off-by: Jussi Kivilinna --- src/hwfeatures.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hwfeatures.c b/src/hwfeatures.c index 06709da7..44453ef1 100644 --- a/src/hwfeatures.c +++ b/src/hwfeatures.c @@ -98,7 +98,7 @@ static struct { HWF_RISCV_ZBB, "riscv-zbb" }, { HWF_RISCV_ZBC, "riscv-zbc" }, { HWF_RISCV_ZVKB, "riscv-zvkb" }, - { HWF_RISCV_ZVKNED, "riscv-zvkg" }, + { HWF_RISCV_ZVKG, "riscv-zvkg" }, { HWF_RISCV_ZVKNED, "riscv-zvkned" }, { HWF_RISCV_ZVKNHA, "riscv-zvknha" }, { HWF_RISCV_ZVKNHB, "riscv-zvknhb" }, -- 2.48.1 From jussi.kivilinna at iki.fi Wed Sep 17 18:02:41 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 17 Sep 2025 19:02:41 +0300 Subject: [PATCH] t-kem: fix test loop iteration Message-ID: <20250917160241.400420-1-jussi.kivilinna@iki.fi> * tests/t-kem.c (check_kem): Reset loop iterator for each algo test loop. -- Signed-off-by: Jussi Kivilinna --- tests/t-kem.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/t-kem.c b/tests/t-kem.c index cafb68b1..dee879a0 100644 --- a/tests/t-kem.c +++ b/tests/t-kem.c @@ -483,17 +483,17 @@ check_kem (int n_loops) info ("Checking KEM.\n"); ntests = 0; - testno = 0; + if ((selected_algo & SELECTED_ALGO_SNTRUP761)) { - for (; testno < n_loops; testno++) + for (testno = 0; testno < n_loops; testno++) test_kem_sntrup761 (testno); ntests += n_loops; } if ((selected_algo & SELECTED_ALGO_CM6688128F)) { - for (; testno < n_loops; testno++) + for (testno = 0; testno < n_loops; testno++) test_kem_mceliece6688128f (testno); ntests += n_loops; } @@ -501,21 +501,21 @@ check_kem (int n_loops) #ifdef USE_KYBER if ((selected_algo & SELECTED_ALGO_MLKEM512)) { - for (; testno < ntests + n_loops; testno++) + for (testno = 0; testno < ntests + n_loops; testno++) test_kem_mlkem512 (testno); ntests += n_loops; } if ((selected_algo & SELECTED_ALGO_MLKEM768)) { - for (; testno < ntests + n_loops; testno++) + for (testno = 0; testno < ntests + n_loops; testno++) test_kem_mlkem768 (testno); ntests += n_loops; } if ((selected_algo & SELECTED_ALGO_MLKEM1024)) { - for (; testno < ntests + n_loops; testno++) + for (testno = 0; testno < ntests + n_loops; testno++) test_kem_mlkem1024 (testno); ntests += n_loops; } @@ -523,14 +523,14 @@ check_kem (int n_loops) if ((selected_algo & SELECTED_ALGO_RAW_X25519)) { - for (; testno < ntests + n_loops; testno++) + for (testno = 0; testno < ntests + n_loops; testno++) test_kem_raw_x25519 (testno); ntests += n_loops; } if ((selected_algo & SELECTED_ALGO_DHKEM25519)) { - for (; testno < ntests + n_loops; testno++) + for (testno = 0; testno < ntests + n_loops; testno++) test_kem_dhkem_x25519 (testno); ntests += n_loops; } -- 2.48.1 From jussi.kivilinna at iki.fi Wed Sep 17 19:37:11 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 17 Sep 2025 20:37:11 +0300 Subject: [PATCH] hwf-x86: remove unused HWF_INTEL_FAST_VPGATHER Message-ID: <20250917173711.799675-1-jussi.kivilinna@iki.fi> * cipher/twofish-avx2-amd64.S (RNOT): Update comment on usage of this register macro. * doc/gcrypt.texi: Remove 'intel-fast-vpgather'. * src/g10lib.h (HWF_INTEL_FAST_VPGATHER): Remove. (HWF_INTEL_RDTSC, HWF_INTEL_SHAEXT, HWF_INTEL_VAES_VPCLMUL, HWF_INTEL_AVX512) (HWF_INTEL_GFNI): Shift bit position to close the gap left by FAST_VPGATHER removal. * src/hwf-x86.c (detect_x86_gnuc): Remove HWF_INTEL_FAST_VPGATHER detection. * src/hwfeatures.c (hwflist): Remove 'intel-fast-vpgather'. -- Signed-off-by: Jussi Kivilinna --- cipher/twofish-avx2-amd64.S | 2 +- doc/gcrypt.texi | 1 - src/g10lib.h | 11 +++--- src/hwf-x86.c | 68 +------------------------------------ src/hwfeatures.c | 1 - 5 files changed, 7 insertions(+), 76 deletions(-) diff --git a/cipher/twofish-avx2-amd64.S b/cipher/twofish-avx2-amd64.S index 3f61f87b..67c1e52e 100644 --- a/cipher/twofish-avx2-amd64.S +++ b/cipher/twofish-avx2-amd64.S @@ -89,7 +89,7 @@ #define RTMP4 RT1 #define RTMP4x RT1x -/* vpgatherdd mask and '-1' */ +/* all bits set mask and '-1' */ #define RNOT %ymm6 #define RNOTx %xmm6 diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 9adf020f..e2b8223a 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -581,7 +581,6 @@ are @item intel-rdrand @item intel-avx @item intel-avx2 - at item intel-fast-vpgather @item intel-rdtsc @item intel-shaext @item intel-vaes-vpclmul diff --git a/src/g10lib.h b/src/g10lib.h index 68ce5405..770ae344 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -234,12 +234,11 @@ char **_gcry_strtokenize (const char *string, const char *delim); #define HWF_INTEL_RDRAND (1 << 11) #define HWF_INTEL_AVX (1 << 12) #define HWF_INTEL_AVX2 (1 << 13) -#define HWF_INTEL_FAST_VPGATHER (1 << 14) -#define HWF_INTEL_RDTSC (1 << 15) -#define HWF_INTEL_SHAEXT (1 << 16) -#define HWF_INTEL_VAES_VPCLMUL (1 << 17) -#define HWF_INTEL_AVX512 (1 << 18) -#define HWF_INTEL_GFNI (1 << 19) +#define HWF_INTEL_RDTSC (1 << 14) +#define HWF_INTEL_SHAEXT (1 << 15) +#define HWF_INTEL_VAES_VPCLMUL (1 << 16) +#define HWF_INTEL_AVX512 (1 << 17) +#define HWF_INTEL_GFNI (1 << 18) #elif defined(HAVE_CPU_ARCH_ARM) diff --git a/src/hwf-x86.c b/src/hwf-x86.c index d9d34c0e..54af1c83 100644 --- a/src/hwf-x86.c +++ b/src/hwf-x86.c @@ -197,7 +197,6 @@ detect_x86_gnuc (void) unsigned int max_cpuid_level; unsigned int fms, family, model; unsigned int result = 0; - unsigned int avoid_vpgather = 0; unsigned int is_amd_cpu = 0; (void)os_supports_avx_avx2_registers; @@ -255,6 +254,7 @@ detect_x86_gnuc (void) { /* This is an AMD CPU. */ is_amd_cpu = 1; + (void)is_amd_cpu; } /* Detect Intel features, that might also be supported by other @@ -411,61 +411,6 @@ detect_x86_gnuc (void) result |= HWF_INTEL_FAST_SHLD; break; } - - /* These Intel Core processors that have AVX2 have slow VPGATHER and - * should be avoided for table-lookup use. */ - switch (model) - { - case 0x3C: - case 0x3F: - case 0x45: - case 0x46: - /* Haswell */ - avoid_vpgather |= 1; - break; - } - - /* These Intel Core processors (skylake to tigerlake) have slow VPGATHER - * because of mitigation introduced by new microcode (2023-08-08) for - * "Downfall" speculative execution vulnerability. */ - switch (model) - { - /* Skylake, Cascade Lake, Cooper Lake */ - case 0x4E: - case 0x5E: - case 0x55: - /* Kaby Lake, Coffee Lake, Whiskey Lake, Amber Lake */ - case 0x8E: - case 0x9E: - /* Cannon Lake */ - case 0x66: - /* Comet Lake */ - case 0xA5: - case 0xA6: - /* Ice Lake */ - case 0x7E: - case 0x6A: - case 0x6C: - /* Tiger Lake */ - case 0x8C: - case 0x8D: - /* Rocket Lake */ - case 0xA7: - avoid_vpgather |= 1; - break; - } - } - else if (is_amd_cpu) - { - /* Non-AVX512 AMD CPUs (pre-Zen4) have slow VPGATHER and should be - * avoided for table-lookup use. */ - avoid_vpgather |= !(result & HWF_INTEL_AVX512); - } - else - { - /* Avoid VPGATHER for non-Intel/non-AMD CPUs as testing is needed to - * make sure it is fast enough. */ - avoid_vpgather |= 1; } #ifdef ENABLE_FORCE_SOFT_HWFEATURES @@ -483,19 +428,8 @@ detect_x86_gnuc (void) * only for those Intel processors that benefit from the SHLD * instruction. Enabled here unconditionally as requested. */ result |= HWF_INTEL_FAST_SHLD; - - /* VPGATHER instructions are used for look-up table based - * implementations which require VPGATHER to be fast enough to beat - * regular parallelized look-up table implementations (see Twofish). - * So far, only Intel processors beginning with Skylake and AMD - * processors starting with Zen4 have had VPGATHER fast enough to be - * enabled. Enable VPGATHER here unconditionally as requested. */ - avoid_vpgather = 0; #endif - if ((result & HWF_INTEL_AVX2) && !avoid_vpgather) - result |= HWF_INTEL_FAST_VPGATHER; - return result; } #endif /* HAS_X86_CPUID */ diff --git a/src/hwfeatures.c b/src/hwfeatures.c index 44453ef1..41a68271 100644 --- a/src/hwfeatures.c +++ b/src/hwfeatures.c @@ -58,7 +58,6 @@ static struct { HWF_INTEL_RDRAND, "intel-rdrand" }, { HWF_INTEL_AVX, "intel-avx" }, { HWF_INTEL_AVX2, "intel-avx2" }, - { HWF_INTEL_FAST_VPGATHER, "intel-fast-vpgather" }, { HWF_INTEL_RDTSC, "intel-rdtsc" }, { HWF_INTEL_SHAEXT, "intel-shaext" }, { HWF_INTEL_VAES_VPCLMUL, "intel-vaes-vpclmul" }, -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 20 15:59:28 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 20 Sep 2025 16:59:28 +0300 Subject: [PATCH] configure.ac: perform RISC-V vector crypto intrinsics bug checks without LTO Message-ID: <20250920135928.3977363-1-jussi.kivilinna@iki.fi> * configure.ac (gcry_cv_riscv_vsha2cl_intrinsics_work) (gcry_cv_riscv_vaes_vs_intrinsics_work): Run check with '-fno-lto' compiler flag. -- Signed-off-by: Jussi Kivilinna --- configure.ac | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configure.ac b/configure.ac index 80d38496..90c513be 100644 --- a/configure.ac +++ b/configure.ac @@ -2934,6 +2934,9 @@ if test "$gcry_cv_cc_riscv_vector_crypto_intrinsics" = "yes" || CFLAGS="$CFLAGS -O2 -march=$MARCH_RVA23U64_WITH_VEC_CRYPTO -mstrict-align" fi + # Disable LTO optimization to generate target instructions + CFLAGS="$CFLAGS -fno-lto" + AC_CACHE_CHECK([whether compiler has working RISC-V __riscv_vsha2cl intrinsics], [gcry_cv_riscv_vsha2cl_intrinsics_work], [gcry_cv_riscv_vsha2cl_intrinsics_work=no @@ -2981,6 +2984,9 @@ if test "$gcry_cv_cc_riscv_vector_crypto_intrinsics" = "yes" || CFLAGS="$CFLAGS -O2" fi + # Disable LTO optimization to generate target instructions + CFLAGS="$CFLAGS -fno-lto" + AC_CACHE_CHECK([whether compiler has working RISC-V __riscv_vaes*_vs intrinsics], [gcry_cv_riscv_vaes_vs_intrinsics_work], [gcry_cv_riscv_vaes_vs_intrinsics_work=no -- 2.48.1 From sam at gentoo.org Sat Sep 20 23:30:47 2025 From: sam at gentoo.org (Sam James) Date: Sat, 20 Sep 2025 22:30:47 +0100 Subject: [PATCH] configure.ac: perform RISC-V vector crypto intrinsics bug checks without LTO In-Reply-To: <20250920135928.3977363-1-jussi.kivilinna@iki.fi> References: <20250920135928.3977363-1-jussi.kivilinna@iki.fi> Message-ID: <87ikhc24mw.fsf@gentoo.org> Jussi Kivilinna writes: > * configure.ac (gcry_cv_riscv_vsha2cl_intrinsics_work) > (gcry_cv_riscv_vaes_vs_intrinsics_work): Run check with '-fno-lto' compiler > flag. I assume this is because of https://gcc.gnu.org/PR110812? If so, a comment referencing it would be nice. > -- > > Signed-off-by: Jussi Kivilinna > --- > configure.ac | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/configure.ac b/configure.ac > index 80d38496..90c513be 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -2934,6 +2934,9 @@ if test "$gcry_cv_cc_riscv_vector_crypto_intrinsics" = "yes" || > CFLAGS="$CFLAGS -O2 -march=$MARCH_RVA23U64_WITH_VEC_CRYPTO -mstrict-align" > fi > > + # Disable LTO optimization to generate target instructions > + CFLAGS="$CFLAGS -fno-lto" > + > AC_CACHE_CHECK([whether compiler has working RISC-V __riscv_vsha2cl intrinsics], > [gcry_cv_riscv_vsha2cl_intrinsics_work], > [gcry_cv_riscv_vsha2cl_intrinsics_work=no > @@ -2981,6 +2984,9 @@ if test "$gcry_cv_cc_riscv_vector_crypto_intrinsics" = "yes" || > CFLAGS="$CFLAGS -O2" > fi > > + # Disable LTO optimization to generate target instructions > + CFLAGS="$CFLAGS -fno-lto" > + > AC_CACHE_CHECK([whether compiler has working RISC-V __riscv_vaes*_vs intrinsics], > [gcry_cv_riscv_vaes_vs_intrinsics_work], > [gcry_cv_riscv_vaes_vs_intrinsics_work=no From jussi.kivilinna at iki.fi Sun Sep 21 07:08:30 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 21 Sep 2025 08:08:30 +0300 Subject: [PATCH v2] configure.ac: perform RISC-V vector crypto intrinsics bug checks without LTO Message-ID: <20250921050830.2373836-1-jussi.kivilinna@iki.fi> * configure.ac (gcry_cv_riscv_vsha2cl_intrinsics_work) (gcry_cv_riscv_vaes_vs_intrinsics_work): Run check with '-fno-lto' compiler flag. -- Signed-off-by: Jussi Kivilinna --- configure.ac | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configure.ac b/configure.ac index 80d38496..e4fcd0a8 100644 --- a/configure.ac +++ b/configure.ac @@ -2934,6 +2934,10 @@ if test "$gcry_cv_cc_riscv_vector_crypto_intrinsics" = "yes" || CFLAGS="$CFLAGS -O2 -march=$MARCH_RVA23U64_WITH_VEC_CRYPTO -mstrict-align" fi + # Disable LTO optimization for following check to generate + # RISC-V instructions in compiler output + CFLAGS="$CFLAGS -fno-lto" + AC_CACHE_CHECK([whether compiler has working RISC-V __riscv_vsha2cl intrinsics], [gcry_cv_riscv_vsha2cl_intrinsics_work], [gcry_cv_riscv_vsha2cl_intrinsics_work=no @@ -2981,6 +2985,10 @@ if test "$gcry_cv_cc_riscv_vector_crypto_intrinsics" = "yes" || CFLAGS="$CFLAGS -O2" fi + # Disable LTO optimization for following check to generate + # RISC-V instructions in compiler output + CFLAGS="$CFLAGS -fno-lto" + AC_CACHE_CHECK([whether compiler has working RISC-V __riscv_vaes*_vs intrinsics], [gcry_cv_riscv_vaes_vs_intrinsics_work], [gcry_cv_riscv_vaes_vs_intrinsics_work=no -- 2.48.1 From jussi.kivilinna at iki.fi Sun Sep 21 06:46:48 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 21 Sep 2025 07:46:48 +0300 Subject: [PATCH] configure.ac: perform RISC-V vector crypto intrinsics bug checks without LTO In-Reply-To: <87ikhc24mw.fsf@gentoo.org> References: <20250920135928.3977363-1-jussi.kivilinna@iki.fi> <87ikhc24mw.fsf@gentoo.org> Message-ID: <8fdadef0-64be-48b7-930b-52138a0fe46d@iki.fi> Hello, On 21/09/2025 00:30, Sam James wrote: > Jussi Kivilinna writes: > >> * configure.ac (gcry_cv_riscv_vsha2cl_intrinsics_work) >> (gcry_cv_riscv_vaes_vs_intrinsics_work): Run check with '-fno-lto' compiler >> flag. > > > I assume this is because of https://gcc.gnu.org/PR110812? If so, a > comment referencing it would be nice. > Issue is with compiling with LTO is not generating target architecture (RISCV) instructions in output. This applies to both GCC and clang, and is not really a compiler bug but problem with these checks. Result was that 'configure' did not detect broken vsha2cl/vaes intrinsics when LTO was enabled for compiler. I'll change "target instructions" in comment to "RISCV instructions in compiler output" to clarify. That GCC issue is for linker not knowing correct RISCV microarchitecture during linking for LTO, so different issue. I did notice that GCC could not build RISCV libgcrypt with LTO and errors I got looked the same as in that bug report. Clang LTO build did work... but with following warning during linking phase: Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi) -Jussi >> -- >> >> Signed-off-by: Jussi Kivilinna >> --- >> configure.ac | 6 ++++++ >> 1 file changed, 6 insertions(+) >> >> diff --git a/configure.ac b/configure.ac >> index 80d38496..90c513be 100644 >> --- a/configure.ac >> +++ b/configure.ac >> @@ -2934,6 +2934,9 @@ if test "$gcry_cv_cc_riscv_vector_crypto_intrinsics" = "yes" || >> CFLAGS="$CFLAGS -O2 -march=$MARCH_RVA23U64_WITH_VEC_CRYPTO -mstrict-align" >> fi >> >> + # Disable LTO optimization to generate target instructions >> + CFLAGS="$CFLAGS -fno-lto" >> + >> AC_CACHE_CHECK([whether compiler has working RISC-V __riscv_vsha2cl intrinsics], >> [gcry_cv_riscv_vsha2cl_intrinsics_work], >> [gcry_cv_riscv_vsha2cl_intrinsics_work=no >> @@ -2981,6 +2984,9 @@ if test "$gcry_cv_cc_riscv_vector_crypto_intrinsics" = "yes" || >> CFLAGS="$CFLAGS -O2" >> fi >> >> + # Disable LTO optimization to generate target instructions >> + CFLAGS="$CFLAGS -fno-lto" >> + >> AC_CACHE_CHECK([whether compiler has working RISC-V __riscv_vaes*_vs intrinsics], >> [gcry_cv_riscv_vaes_vs_intrinsics_work], >> [gcry_cv_riscv_vaes_vs_intrinsics_work=no From jussi.kivilinna at iki.fi Mon Sep 22 07:35:18 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 22 Sep 2025 08:35:18 +0300 Subject: [PATCH] mceliece6688128f: fix UBSAN runtime errors Message-ID: <20250922053518.1887512-1-jussi.kivilinna@iki.fi> * cipher/mceliece6688128f.c (cbrecursion): Fix left shift of signed integer by too many places, by casting to unsigned integer before shift. (syndrome): Fix misaligned memory loads by using 'bufhelp.h'. -- There was multiple undefined behaviour sanitizer warnings with mceliece668128f which have been fixed by this commit: $ tests/t-kem ../../cipher/mceliece6688128f.c:1766:37: runtime error: left shift of 73010 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1769:37: runtime error: left shift of 71034 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1792:39: runtime error: left shift of 72996 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1800:41: runtime error: left shift of 71344 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1807:43: runtime error: left shift of 68334 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1834:23: runtime error: left shift of 72247 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1833:19: runtime error: left shift of 136871 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1781:41: runtime error: left shift of 66551 by 20 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:2261:15: runtime error: load of misaligned address 0x7ffd13d3ad84 for type 'const uint64_t', which requires 8 byte alignment 0x7ffd13d3ad84: note: pointer points here d8 7f e7 3c 61 1d b1 60 68 9b ff 4e 95 da 54 31 4b ca b9 7f e2 3b 06 a5 51 e3 7f 74 14 99 81 44 ^ t-kem: 70 tests done Signed-off-by: Jussi Kivilinna --- cipher/mceliece6688128f.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c index 6ad3eecb..a5890dfa 100644 --- a/cipher/mceliece6688128f.c +++ b/cipher/mceliece6688128f.c @@ -131,6 +131,7 @@ #endif #include "g10lib.h" +#include "bufhelp.h" #include "mceliece6688128f.h" static void @@ -1763,10 +1764,10 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in } /* B = (p<<16)+c */ - for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<16)|x; /* A = (pibar<<16)+id */ int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ - for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ int32_sort(A,n); /* A = (id<<16)+pibar^2 */ if (w <= 10) { @@ -1778,7 +1779,7 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ int32_sort(A,n); /* A = (id<<16)+p^{-1} */ - for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ for (x = 0;x < n;++x) { @@ -1789,7 +1790,7 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in } for (x = 0;x < n;++x) B[x] &= 0x3ff; } else { - for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + for (x = 0;x < n;++x) B[x] = ((u32)A[x]<<16)|(B[x]&0xffff); for (i = 1;i < w-1;++i) { /* B = (p<<16)+c */ @@ -1797,14 +1798,14 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; int32_sort(A,n); /* A = (id<<16)+p^(-1) */ - for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<16)|(B[x]&0xffff); /* A = p^(-1)<<16+c */ if (i < w-2) { for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); /* B = (p^(-1)<<16)+p */ int32_sort(B,n); /* B = (id<<16)+p^(-2) */ - for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + for (x = 0;x < n;++x) B[x] = ((u32)B[x]<<16)|(A[x]&0xffff); /* B = (p^(-2)<<16)+c */ } @@ -1830,8 +1831,8 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in out[pos>>3] ^= fj<<(pos&7); pos += step; - B[lx] = (A[lx]<<16)|Fx; - B[lx+1] = (A[lx+1]<<16)|Fx1; + B[lx] = ((u32)A[lx]<<16)|Fx; + B[lx+1] = ((u32)A[lx+1]<<16)|Fx1; } /* B = (pi^(-1)<<16)+F */ @@ -2242,8 +2243,8 @@ static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e { uint64_t b; - const uint64_t *pk_ptr; - const uint64_t *e_ptr = ((uint64_t *) (e + SYND_BYTES)); + const unsigned char *pk_ptr; + const unsigned char *e_ptr = (e + SYND_BYTES); int i, j; @@ -2254,13 +2255,13 @@ static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e for (i = 0; i < PK_NROWS; i++) { - pk_ptr = ((uint64_t *) (pk + PK_ROW_BYTES * i)); + pk_ptr = (pk + PK_ROW_BYTES * i); b = 0; for (j = 0; j < PK_NCOLS/64; j++) - b ^= pk_ptr[j] & e_ptr[j]; + b ^= buf_get_he64(&pk_ptr[j*8]) & buf_get_he64(&e_ptr[j*8]); - b ^= ((uint32_t *) &pk_ptr[j])[0] & ((uint32_t *) &e_ptr[j])[0]; + b ^= buf_get_he64(&pk_ptr[j*8]) & buf_get_he32(&e_ptr[j*8]); b ^= b >> 32; b ^= b >> 16; -- 2.48.1 From jussi.kivilinna at iki.fi Mon Sep 22 07:40:01 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 22 Sep 2025 08:40:01 +0300 Subject: [PATCH v2] mceliece6688128f: fix UBSAN runtime errors Message-ID: <20250922054001.1901706-1-jussi.kivilinna@iki.fi> * cipher/mceliece6688128f.c (cbrecursion): Fix left shift of signed integer by too many places, by casting to unsigned integer before shift. (syndrome): Fix misaligned memory loads by using 'bufhelp.h'. -- There was multiple undefined behaviour sanitizer warnings with mceliece668128f which have been fixed by this commit: $ tests/t-kem ../../cipher/mceliece6688128f.c:1766:37: runtime error: left shift of 73010 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1769:37: runtime error: left shift of 71034 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1792:39: runtime error: left shift of 72996 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1800:41: runtime error: left shift of 71344 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1807:43: runtime error: left shift of 68334 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1834:23: runtime error: left shift of 72247 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1833:19: runtime error: left shift of 136871 by 16 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:1781:41: runtime error: left shift of 66551 by 20 places cannot be represented in type 'int' ../../cipher/mceliece6688128f.c:2261:15: runtime error: load of misaligned address 0x7ffd13d3ad84 for type 'const uint64_t', which requires 8 byte alignment 0x7ffd13d3ad84: note: pointer points here d8 7f e7 3c 61 1d b1 60 68 9b ff 4e 95 da 54 31 4b ca b9 7f e2 3b 06 a5 51 e3 7f 74 14 99 81 44 ^ t-kem: 70 tests done Signed-off-by: Jussi Kivilinna --- cipher/mceliece6688128f.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c index 6ad3eecb..ca1952b5 100644 --- a/cipher/mceliece6688128f.c +++ b/cipher/mceliece6688128f.c @@ -131,6 +131,7 @@ #endif #include "g10lib.h" +#include "bufhelp.h" #include "mceliece6688128f.h" static void @@ -1763,10 +1764,10 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in } /* B = (p<<16)+c */ - for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<16)|x; /* A = (pibar<<16)+id */ int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ - for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ int32_sort(A,n); /* A = (id<<16)+pibar^2 */ if (w <= 10) { @@ -1778,7 +1779,7 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ int32_sort(A,n); /* A = (id<<16)+p^{-1} */ - for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ for (x = 0;x < n;++x) { @@ -1789,7 +1790,7 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in } for (x = 0;x < n;++x) B[x] &= 0x3ff; } else { - for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + for (x = 0;x < n;++x) B[x] = ((u32)A[x]<<16)|(B[x]&0xffff); for (i = 1;i < w-1;++i) { /* B = (p<<16)+c */ @@ -1797,14 +1798,14 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; int32_sort(A,n); /* A = (id<<16)+p^(-1) */ - for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<16)|(B[x]&0xffff); /* A = p^(-1)<<16+c */ if (i < w-2) { for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); /* B = (p^(-1)<<16)+p */ int32_sort(B,n); /* B = (id<<16)+p^(-2) */ - for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + for (x = 0;x < n;++x) B[x] = ((u32)B[x]<<16)|(A[x]&0xffff); /* B = (p^(-2)<<16)+c */ } @@ -1830,8 +1831,8 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in out[pos>>3] ^= fj<<(pos&7); pos += step; - B[lx] = (A[lx]<<16)|Fx; - B[lx+1] = (A[lx+1]<<16)|Fx1; + B[lx] = ((u32)A[lx]<<16)|Fx; + B[lx+1] = ((u32)A[lx+1]<<16)|Fx1; } /* B = (pi^(-1)<<16)+F */ @@ -2242,8 +2243,8 @@ static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e { uint64_t b; - const uint64_t *pk_ptr; - const uint64_t *e_ptr = ((uint64_t *) (e + SYND_BYTES)); + const unsigned char *pk_ptr; + const unsigned char *e_ptr = (e + SYND_BYTES); int i, j; @@ -2254,13 +2255,13 @@ static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e for (i = 0; i < PK_NROWS; i++) { - pk_ptr = ((uint64_t *) (pk + PK_ROW_BYTES * i)); + pk_ptr = (pk + PK_ROW_BYTES * i); b = 0; for (j = 0; j < PK_NCOLS/64; j++) - b ^= pk_ptr[j] & e_ptr[j]; + b ^= buf_get_he64(&pk_ptr[j*8]) & buf_get_he64(&e_ptr[j*8]); - b ^= ((uint32_t *) &pk_ptr[j])[0] & ((uint32_t *) &e_ptr[j])[0]; + b ^= buf_get_he32(&pk_ptr[j*8]) & buf_get_he32(&e_ptr[j*8]); b ^= b >> 32; b ^= b >> 16; -- 2.48.1 From wk at gnupg.org Tue Sep 23 12:21:32 2025 From: wk at gnupg.org (Werner Koch) Date: Tue, 23 Sep 2025 12:21:32 +0200 Subject: Are we ready for a Libgcrypt 1.12 ? Message-ID: <87ikh979lf.fsf@jacob.g10code.de> Hi! Do we have any blockers for 1.12.0 ? This will be the next LTS release for which the API will be mostly fixed. The only thing I would like to wait for is to see whether migrating gpgsm to KEM functions can be done with the current Libgcrypt code. Salam-Shalom, Werner -- The pioneers of a warless world are the youth that refuse military service. - A. Einstein -------------- next part -------------- A non-text attachment was scrubbed... Name: openpgp-digital-signature.asc Type: application/pgp-signature Size: 284 bytes Desc: not available URL: From jussi.kivilinna at iki.fi Thu Sep 25 08:28:22 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 25 Sep 2025 09:28:22 +0300 Subject: [PATCH] kdf: Avoid redundant memcpy() In-Reply-To: <20250902071427.1781-1-glin@suse.com> References: <20250902071427.1781-1-glin@suse.com> Message-ID: <2f6dc952-8bfc-429e-9f9c-61a82b196f54@iki.fi> Hello, Thanks for the patch. Before this can be applied, we'd need "DCO" from you. Please check doc/HACKING for "License policy" and about sending "Libgcrypt Developer's Certificate of Origin". -Jussi On 02/09/2025 10:14, Gary Lin via Gcrypt-devel wrote: > * cipher/kdf.c (fill_block): Xor 'ref_block' and 'prev_block' directly to > avoid a redundant memcpy(). > > Signed-off-by: Gary Lin > --- > cipher/kdf.c | 9 +++++++-- > 1 file changed, 7 insertions(+), 2 deletions(-) > > diff --git a/cipher/kdf.c b/cipher/kdf.c > index 71156ea4..16cec4e4 100644 > --- a/cipher/kdf.c > +++ b/cipher/kdf.c > @@ -588,9 +588,14 @@ fill_block (const u64 *prev_block, const u64 *ref_block, u64 *curr_block, > u64 block_tmp[ARGON2_WORDS_IN_BLOCK]; > int i; > > - memcpy (block_r, ref_block, 1024); > if (prev_block) > - xor_block (block_r, prev_block); > + { > + for (i = 0; i < ARGON2_WORDS_IN_BLOCK; i++) > + block_r[i] = ref_block[i] ^ prev_block[i]; > + } > + else > + memcpy (block_r, ref_block, 1024); > + > memcpy (block_tmp, block_r, 1024); > > if (with_xor) From jussi.kivilinna at iki.fi Fri Sep 26 08:53:01 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 26 Sep 2025 09:53:01 +0300 Subject: [PATCH 1/2] mceliece6688128f: fix stack overflow crash on win64/wine Message-ID: <20250926065302.1693112-1-jussi.kivilinna@iki.fi> * cipher/mceliece6688128f.c (pk_gen): Remove 'mat' array allocation and rename function to ... (pk_gen_mat): ... this. (pk_gen): New warper for 'pk_gen_mat' with dynamic allocation of 'mat' array. -- Huge array allocations from stack are not always guaranteed to work on every target platform, so avoid allocating multi-megabyte 'mat' array from stack. Signed-off-by: Jussi Kivilinna --- cipher/mceliece6688128f.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c index ca1952b5..c15c2d14 100644 --- a/cipher/mceliece6688128f.c +++ b/cipher/mceliece6688128f.c @@ -3315,16 +3315,15 @@ static int mov_columns(uint64_t mat[][ (SYS_N + 63) / 64 ], int16_t * pi, uint64 return 0; } -static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm, int16_t * pi, uint64_t * pivots) -{ - const int nblocks_H = (SYS_N + 63) / 64; - const int nblocks_I = (PK_NROWS + 63) / 64; +#define nblocks_H ((SYS_N + 63) / 64) +#define nblocks_I ((PK_NROWS + 63) / 64) +static int pk_gen_mat(unsigned char * pk, const unsigned char * irr, uint32_t * perm, int16_t * pi, uint64_t * pivots, + uint64_t mat[ PK_NROWS ][ nblocks_H ]) +{ int i, j, k; int row, c; - uint64_t mat[ PK_NROWS ][ nblocks_H ]; - uint64_t mask; vec irr_int[2][ GFBITS ]; @@ -3460,6 +3459,16 @@ static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm } +static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm, int16_t * pi, uint64_t * pivots) +{ + /* Allocate large array from heap to avoid stack overflow crash on Win32/Wine. */ + uint64_t *mat = xmalloc(sizeof(uint64_t) * PK_NROWS * nblocks_H); + int ret = pk_gen_mat(pk, irr, perm, pi, pivots, (void *)mat); + xfree(mat); + return ret; +} + + /* from libmceliece-20230612/crypto_kem/6688128f/vec/sk_gen.c */ /* This file is for secret-key generation -- 2.48.1 From jussi.kivilinna at iki.fi Fri Sep 26 08:53:02 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 26 Sep 2025 09:53:02 +0300 Subject: [PATCH 2/2] t-kem: add info print for each algoritm In-Reply-To: <20250926065302.1693112-1-jussi.kivilinna@iki.fi> References: <20250926065302.1693112-1-jussi.kivilinna@iki.fi> Message-ID: <20250926065302.1693112-2-jussi.kivilinna@iki.fi> * tests/t-kem.c (test_kem_sntrup761, test_kem_mceliece6688128f) (test_kem_mlkem512, test_kem_mlkem768, test_kem_mlkem1024, test_kem_raw_x25519) (test_kem_dhkem_x25519): Add 'Checking ' info print. -- Signed-off-by: Jussi Kivilinna --- tests/t-kem.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/t-kem.c b/tests/t-kem.c index dee879a0..4e215b0f 100644 --- a/tests/t-kem.c +++ b/tests/t-kem.c @@ -43,6 +43,8 @@ test_kem_sntrup761 (int testno) uint8_t key1[GCRY_KEM_SNTRUP761_SHARED_LEN]; uint8_t key2[GCRY_KEM_SNTRUP761_SHARED_LEN]; + info (" Checking SNTRUP761.\n"); + err = gcry_kem_genkey (GCRY_KEM_SNTRUP761, pubkey, GCRY_KEM_SNTRUP761_PUBKEY_LEN, seckey, GCRY_KEM_SNTRUP761_SECKEY_LEN, @@ -102,6 +104,8 @@ test_kem_mceliece6688128f (int testno) uint8_t key1[GCRY_KEM_CM6688128F_SHARED_LEN]; uint8_t key2[GCRY_KEM_CM6688128F_SHARED_LEN]; + info (" Checking CM6688128F.\n"); + err = gcry_kem_genkey (GCRY_KEM_CM6688128F, pubkey, GCRY_KEM_CM6688128F_PUBKEY_LEN, seckey, GCRY_KEM_CM6688128F_SECKEY_LEN, @@ -162,6 +166,8 @@ test_kem_mlkem512 (int testno) uint8_t key1[GCRY_KEM_MLKEM512_SHARED_LEN]; uint8_t key2[GCRY_KEM_MLKEM512_SHARED_LEN]; + info (" Checking MLKEM512.\n"); + err = gcry_kem_genkey (GCRY_KEM_MLKEM512, pubkey, GCRY_KEM_MLKEM512_PUBKEY_LEN, seckey, GCRY_KEM_MLKEM512_SECKEY_LEN, @@ -220,6 +226,8 @@ test_kem_mlkem768 (int testno) uint8_t key1[GCRY_KEM_MLKEM768_SHARED_LEN]; uint8_t key2[GCRY_KEM_MLKEM768_SHARED_LEN]; + info (" Checking MLKEM768.\n"); + err = gcry_kem_genkey (GCRY_KEM_MLKEM768, pubkey, GCRY_KEM_MLKEM768_PUBKEY_LEN, seckey, GCRY_KEM_MLKEM768_SECKEY_LEN, @@ -278,6 +286,8 @@ test_kem_mlkem1024 (int testno) uint8_t key1[GCRY_KEM_MLKEM1024_SHARED_LEN]; uint8_t key2[GCRY_KEM_MLKEM1024_SHARED_LEN]; + info (" Checking MLKEM1024.\n"); + err = gcry_kem_genkey (GCRY_KEM_MLKEM1024, pubkey, GCRY_KEM_MLKEM1024_PUBKEY_LEN, seckey, GCRY_KEM_MLKEM1024_SECKEY_LEN, @@ -338,6 +348,8 @@ test_kem_raw_x25519 (int testno) uint8_t key1[GCRY_KEM_RAW_X25519_SHARED_LEN]; uint8_t key2[GCRY_KEM_RAW_X25519_SHARED_LEN]; + info (" Checking X25519.\n"); + err = gcry_kem_genkey (GCRY_KEM_RAW_X25519, pubkey, GCRY_KEM_ECC_X25519_PUBKEY_LEN, seckey, GCRY_KEM_ECC_X25519_SECKEY_LEN, @@ -406,6 +418,8 @@ test_kem_dhkem_x25519 (int testno) uint8_t key1[GCRY_KEM_DHKEM25519_SHARED_LEN]; uint8_t key2[GCRY_KEM_DHKEM25519_SHARED_LEN]; + info (" Checking DHKEM25519.\n"); + err = gcry_kem_genkey (GCRY_KEM_DHKEM25519, pubkey, GCRY_KEM_DHKEM25519_PUBKEY_LEN, seckey, GCRY_KEM_DHKEM25519_SECKEY_LEN, -- 2.48.1 From pikolasikolatest1 at gmail.com Fri Sep 26 20:35:23 2025 From: pikolasikolatest1 at gmail.com (Rabha hssni) Date: Fri, 26 Sep 2025 19:35:23 +0100 Subject: =?UTF-8?B?2KPZgdi22YQgMTAg2YXZiNin2YLYuSDZhNmE2KjYrdirINi52YYg2LnZhdmEINmB2Yog?= =?UTF-8?B?2KfZhNmF2LrYsdioICgyMDI1KQ==?= Message-ID: ???? 10 ????? ????? ?? ??? ?? ?????? (2025) ??? ??? ?????? ?? ???? ????? ????????? ????? ?? ?? ???????? ??????? ?????? ????? ???????? ?? ???? ???? ??????? ?? ?????? ????? ???? ???? ??? ????? ????? ????????? ??????. ???? ??? ??????? ????? ?????? ?? ???? ??????? ?? ?????? ??????? ???? ?? ?????? ????? ?? ??????? ???????? ????? ????? ???? ??? ????? ???????? ??????? ????? ?????. ??? ??? ???? ?? ????? ?? ??? ?? ????? ????? ????? ???????? ??? ???? ??? ???????? ???? ????? ???????? ?? ??? linkedin ???????. ??? ???? ????? ???? ??? ??????? ?????? ????? ??? ????? ????? ????? ?????. ?? ???? ??? ?????? ???????? ????? ?????? ?????? ??? ????? ?????? ??????? ?????? ???? ????? ??????? ??? ?????? ????? ?????? ??? ???? ??????? ???? ?? ???? ??????. 1. TARGIR.c om ? ??? ???? ?????? ????? ??????? ???? ???? TARGIR ?? ???? ????? ????? ??????? ????? ?? ??????? ??? ???? ??? ??? ?????? ?????? ???? ????? ?? ???? ????? ???????? ???????? ??????. ???? ?????? ?????? ??? ????? ????? ???? ??? ????? ???? ?????? ???? ?????? ????? ????? ?????? ??? ?????? ????? ????? ???????? ?? ????? ??? ????? ??? ????? ???????? ?? ??? ?????? ??????? ???????. ???? ??? ???? ?? ????? ?? ?????? ???????? ?? ???? ?? ????? ?? ??? ??????? ?? ??? ????? ???? ?? ????? ??? ??????? ??????? ?? ?????? ????????? ??? TARGIR ???? ?????? ???? ??????. ??? ???? ?? ??????? ??? ????? ??? ???? ??????? ???? ?????? ??????? ???????? ????? ????????? ???? ?????? ?????? ?? ???? ????? ??????? ?? ?????? ???????. ?????? TARGIR: ??????? ????? ????? ?????? ?? ????? ????????. ????? ??????? ???? ?????? ??? ??????? ?? ??????. ????? ?????? ?????? ???? ????? ????????. ??????? ???? ??????? ??????? ??? ??????? ????????. ???? ??? ?????? ??????? ??? ???? ?? ????? ?? ??????? ?????? ?? ?????? ????????? ???????? ???????? ????????. ???? ?????? ????? ?????? ???? ??????? ??????? ?? ????? ???? ??? kpc ?????? maximus ?????? ?ngha ?????? ???????? ??? ??? ??? ???? uep ???????. ??? ???? ?????? ????? ?? ???????? ????? ??????? ?? ??? ????? ?????? ??? ???? ???????? ???? ???? ????? ?? ???????? ??????? ????????? ??????? ??????. ????? ????? ??????? ??? ??????? ??????? ?? ????? ???????? ??? ????? ??????? ???????? ??????? ????? ???? ???????. ???? ?????? ????? ?? ????? ?????? ??? ???????? ?????? ?????? ??????? ???????? ?????? ???? ???????. ??? ???? ?? ?????? ??? ??????? ???????? ?????? ????? ???????? ????? 2022 ?? ????? ???????? ????? ??? ????? ???? ??????. -------------- next part -------------- An HTML attachment was scrubbed... URL: From jcb62281 at gmail.com Sat Sep 27 01:19:00 2025 From: jcb62281 at gmail.com (Jacob Bachmeyer) Date: Fri, 26 Sep 2025 18:19:00 -0500 Subject: [PATCH 1/2] mceliece6688128f: fix stack overflow crash on win64/wine In-Reply-To: <20250926065302.1693112-1-jussi.kivilinna@iki.fi> References: <20250926065302.1693112-1-jussi.kivilinna@iki.fi> Message-ID: <437e0196-6a62-4a11-bc14-5420c7a05d97@gmail.com> On 9/26/25 01:53, Jussi Kivilinna wrote: > * cipher/mceliece6688128f.c (pk_gen): Remove 'mat' array allocation and > rename function to ... > (pk_gen_mat): ... this. > (pk_gen): New warper for 'pk_gen_mat' with dynamic allocation of 'mat' array. Typo?? Did you mean "wrapper"? Why do it this way instead of just adding xmalloc()/xfree() calls to pk_gen()?? Also, should the buffer be zeroed before releasing it? -- Jacob From jussi.kivilinna at iki.fi Sat Sep 27 08:16:07 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 09:16:07 +0300 Subject: [PATCH 1/2] mceliece6688128f: fix stack overflow crash on win64/wine In-Reply-To: <437e0196-6a62-4a11-bc14-5420c7a05d97@gmail.com> References: <20250926065302.1693112-1-jussi.kivilinna@iki.fi> <437e0196-6a62-4a11-bc14-5420c7a05d97@gmail.com> Message-ID: Hello, On 27/09/2025 02:19, Jacob Bachmeyer wrote: > On 9/26/25 01:53, Jussi Kivilinna wrote: >> * cipher/mceliece6688128f.c (pk_gen): Remove 'mat' array allocation and >> rename function to ... >> (pk_gen_mat): ... this. >> (pk_gen): New warper for 'pk_gen_mat' with dynamic allocation of 'mat' array. > > Typo?? Did you mean "wrapper"? > Yes, typo. > Why do it this way instead of just adding xmalloc()/xfree() calls to pk_gen()?? Also, should the buffer be zeroed before releasing it? > I wanted to avoid diverging too much from the original, to avoid having to make greater changes to original pk_gen() function. With allocation in pk_gen(), 'mat' would change from 2d array to, for example, simple pointer and then all 'mat[][]' accesses would need to be changed. Or 'mat' could be changed to 'struct { uint64_t arr[][] } *mat' and change accesses to 'mat->arr[][]'. That buffer probably should be zeroed after although it was not being cleared. I'll add that for v2 of patch. About memory zeroing in general... I see that PQ algorithms use quite a lot of stack arrays in their implementations (some quite large allocations too) but there is no stack memory wiping in place. Maybe there should be? I guess simplest way to wipe used stack would be to add appropriately sized _gcry_burn_stack() calls after each PQ function call, for example in 'kem.c'. -Jussi From ametzler at bebt.de Sat Sep 27 07:27:56 2025 From: ametzler at bebt.de (Andreas Metzler) Date: Sat, 27 Sep 2025 07:27:56 +0200 Subject: Are we ready for a Libgcrypt 1.12 ? In-Reply-To: <87ikh979lf.fsf@jacob.g10code.de> References: <87ikh979lf.fsf@jacob.g10code.de> Message-ID: On 2025-09-23 Werner Koch via Gcrypt-devel wrote: > Hi! > Do we have any blockers for 1.12.0 ? This will be the next LTS release > for which the API will be mostly fixed. > The only thing I would like to wait for is to see whether migrating > gpgsm to KEM functions can be done with the current Libgcrypt code. Good morning, whatever choice you make I would appreciate a beta/rc before the release. TIA! cu Andreas -- `What a good friend you are to him, Dr. Maturin. His other friends are so grateful to you.' `I sew his ears on from time to time, sure' From jussi.kivilinna at iki.fi Sat Sep 27 09:02:54 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 10:02:54 +0300 Subject: [PATCH v2] mceliece6688128f: fix stack overflow crash on win64/wine Message-ID: <20250927070254.1705049-1-jussi.kivilinna@iki.fi> * cipher/mceliece6688128f.c (pk_gen): Remove 'mat' array allocation and rename function to ... (pk_gen_mat): ... this. (pk_gen): New wrapper for 'pk_gen_mat' with dynamic allocation of 'mat' array. -- Huge array allocations from stack are not always guaranteed to work on every target platform, so avoid allocating multi-megabyte 'mat' array from stack. v2: zero 'mat' array after use. Signed-off-by: Jussi Kivilinna --- cipher/mceliece6688128f.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c index ca1952b5..bdc7f265 100644 --- a/cipher/mceliece6688128f.c +++ b/cipher/mceliece6688128f.c @@ -3315,16 +3315,15 @@ static int mov_columns(uint64_t mat[][ (SYS_N + 63) / 64 ], int16_t * pi, uint64 return 0; } -static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm, int16_t * pi, uint64_t * pivots) -{ - const int nblocks_H = (SYS_N + 63) / 64; - const int nblocks_I = (PK_NROWS + 63) / 64; +#define nblocks_H ((SYS_N + 63) / 64) +#define nblocks_I ((PK_NROWS + 63) / 64) +static int pk_gen_mat(unsigned char * pk, const unsigned char * irr, uint32_t * perm, int16_t * pi, uint64_t * pivots, + uint64_t mat[ PK_NROWS ][ nblocks_H ]) +{ int i, j, k; int row, c; - uint64_t mat[ PK_NROWS ][ nblocks_H ]; - uint64_t mask; vec irr_int[2][ GFBITS ]; @@ -3460,6 +3459,18 @@ static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm } +static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm, int16_t * pi, uint64_t * pivots) +{ + /* Allocate large array from heap to avoid stack overflow crash on Win32/Wine. */ + unsigned int sizeof_mat = sizeof(uint64_t) * PK_NROWS * nblocks_H; + void *mat = xmalloc(sizeof_mat); + int ret = pk_gen_mat(pk, irr, perm, pi, pivots, mat); + wipememory(mat, sizeof_mat); + xfree(mat); + return ret; +} + + /* from libmceliece-20230612/crypto_kem/6688128f/vec/sk_gen.c */ /* This file is for secret-key generation -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 27 09:54:10 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 10:54:10 +0300 Subject: [PATCH 01/10] rijndael: harden mask generation against branch optimization Message-ID: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> * cipher/rijndael.c (do_setkey): Generate 'rcon' mask with const-time helper. (_gcry_aes_xts_crypt): Generate tweak mask with const-time helper. -- Signed-off-by: Jussi Kivilinna --- cipher/rijndael.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cipher/rijndael.c b/cipher/rijndael.c index 972685b4..910073d2 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -991,7 +991,7 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen, { j = 0; temp0 = sbox4(rol(temp0, 24)) ^ rcon; - rcon = ((rcon << 1) ^ (-(rcon >> 7) & 0x1b)) & 0xff; + rcon = ((rcon << 1) ^ (ct_ulong_gen_mask(rcon >> 7) & 0x1b)) & 0xff; } else if (KC == 8 && j == 4) { @@ -1760,7 +1760,7 @@ _gcry_aes_xts_crypt (void *context, unsigned char *tweak, buf_put_le64 (outbuf + 8, tmp_hi); /* Generate next tweak. */ - carry = -(tweak_next_hi >> 63) & 0x87; + carry = ct_ulong_gen_mask(tweak_next_hi >> 63) & 0x87; tweak_next_hi = (tweak_next_hi << 1) + (tweak_next_lo >> 63); tweak_next_lo = (tweak_next_lo << 1) ^ carry; -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 27 09:54:12 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 10:54:12 +0300 Subject: [PATCH 03/10] mpih-pow: harden condition calculation against branch optimization In-Reply-To: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> References: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> Message-ID: <20250927075419.1923877-3-jussi.kivilinna@iki.fi> * mpi/mpih-pow.c (mont_reduc): Pass condition code through mask generator to avoid optimization to branch by certain compilers. -- Signed-off-by: Jussi Kivilinna --- mpi/mpih-pow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpi/mpih-pow.c b/mpi/mpih-pow.c index 649052f6..fb6cd9f3 100644 --- a/mpi/mpih-pow.c +++ b/mpi/mpih-pow.c @@ -97,7 +97,7 @@ mont_reduc (mpi_ptr_t rp, mpi_ptr_t tp, cy0 = _gcry_mpih_sub_n (rp, tp + n, mp, n); _gcry_mpih_set_cond (rp, tp + n, n, - mpih_limb_is_not_zero (cy0) + ct_ulong_gen_mask (mpih_limb_is_not_zero (cy0)) & mpih_limb_is_zero (cy1)); } -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 27 09:54:14 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 10:54:14 +0300 Subject: [PATCH 05/10] sntrup761: harden mask generation against branch optimization In-Reply-To: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> References: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> Message-ID: <20250927075419.1923877-5-jussi.kivilinna@iki.fi> * cipher/sntrup761.c (int32_MINMAX, uint32_divmod_uint14) (int32_divmod_uint14, int16_t_nonzero_mask, int16_t_negative_mask) (Ciphertexts_diff_mask): Generate mask with const-time helper function. -- Signed-off-by: Jussi Kivilinna --- cipher/sntrup761.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/cipher/sntrup761.c b/cipher/sntrup761.c index 7d6b85cc..19e4796c 100644 --- a/cipher/sntrup761.c +++ b/cipher/sntrup761.c @@ -34,6 +34,7 @@ #endif #include "sntrup761.h" +#include "const-time.h" /* from supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc */ #define int32_MINMAX(a,b) \ @@ -41,7 +42,7 @@ do { \ int64_t ab = (int64_t)b ^ (int64_t)a; \ int64_t c = (int64_t)b - (int64_t)a; \ c ^= ab & (c ^ b); \ - c >>= 31; \ + c = ct_ulong_gen_mask((uint64_t)c >> 63); \ c &= ab; \ a ^= c; \ b ^= c; \ @@ -189,7 +190,7 @@ uint32_divmod_uint14 (uint32_t * q, uint16_t * r, uint32_t x, uint16_t m) x -= m; *q += 1; - mask = -(x >> 31); + mask = ct_ulong_gen_mask(x >> 31); x += mask & (uint32_t) m; *q += mask; /* x < m */ @@ -220,7 +221,7 @@ int32_divmod_uint14 (int32_t * q, uint16_t * r, int32_t x, uint16_t m) uint32_divmod_uint14 (&uq2, &ur2, 0x80000000, m); ur -= ur2; uq -= uq2; - mask = -(uint32_t) (ur >> 15); + mask = ct_ulong_gen_mask(ur >> 15); ur += mask & m; uq += mask; *r = ur; @@ -378,7 +379,7 @@ int16_t_nonzero_mask (int16_t x) uint32_t v = u; /* 0, else 1...65535 */ v = -v; /* 0, else 2^32-65535...2^32-1 */ v >>= 31; /* 0, else 1 */ - return -v; /* 0, else -1 */ + return ct_ulong_gen_mask(v); /* 0, else -1 */ } /* return -1 if x<0; otherwise return 0 */ @@ -387,9 +388,7 @@ int16_t_negative_mask (int16_t x) { uint16_t u = x; u >>= 15; - return -(int) u; - /* alternative with gcc -fwrapv: */ - /* x>>15 compiles to CPU's arithmetic right shift */ + return (int)ct_ulong_gen_mask(u); } /* ----- arithmetic mod 3 */ @@ -1037,7 +1036,7 @@ Ciphertexts_diff_mask (const unsigned char *c, const unsigned char *c2) while (len-- > 0) differentbits |= (*c++) ^ (*c2++); - return (1 & ((differentbits - 1) >> 8)) - 1; + return ct_ulong_gen_mask(ct_is_not_zero(differentbits)); } /* k = Decap(c,sk) */ -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 27 09:54:16 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 10:54:16 +0300 Subject: [PATCH 07/10] mceliece6688128f: harden mask generation against branch optimization In-Reply-To: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> References: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> Message-ID: <20250927075419.1923877-7-jussi.kivilinna@iki.fi> * cipher/mceliece6688128f.c (crypto_int64_negative_mask) (crypto_int16_negative_mask, crypto_int32_negative_mask) (crypto_uint64_signed_negative_mask, crypto_uint16_signed_negative_mask) (crypto_uint32_signed_negative_mask, mask_nonzero, mask_leq, vec_cmov) (layer, gen_e, gf_mul, same_mask, pk_gen): Generate masks with const-time helper function. * src/const-time.h (ct_u64_gen_mask, ct_u64_gen_inv_mask): New. -- Signed-off-by: Jussi Kivilinna --- cipher/mceliece6688128f.c | 34 +++++++++++++++++----------------- src/const-time.h | 3 +++ 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c index bdc7f265..4c4eb0bd 100644 --- a/cipher/mceliece6688128f.c +++ b/cipher/mceliece6688128f.c @@ -132,6 +132,7 @@ #include "g10lib.h" #include "bufhelp.h" +#include "const-time.h" #include "mceliece6688128f.h" static void @@ -195,7 +196,7 @@ static void crypto_declassify(void *crypto_declassify_v,long long crypto_declass GCC_ATTR_UNUSED static crypto_int64 crypto_int64_negative_mask(crypto_int64 crypto_int64_x) { - return crypto_int64_x >> (64-1); + return ct_u64_gen_mask((u64)crypto_int64_x >> (64-1)); } GCC_ATTR_UNUSED @@ -287,7 +288,7 @@ static void crypto_int64_minmax(crypto_int64 *crypto_int64_a,crypto_int64 *crypt GCC_ATTR_UNUSED static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) { - return crypto_int16_x >> (16-1); + return ct_ulong_gen_mask((u16)crypto_int16_x >> (16-1)); } GCC_ATTR_UNUSED @@ -379,7 +380,7 @@ static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypt GCC_ATTR_UNUSED static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) { - return crypto_int32_x >> (32-1); + return ct_ulong_gen_mask((u32)crypto_int32_x >> (32-1)); } GCC_ATTR_UNUSED @@ -472,7 +473,7 @@ static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypt GCC_ATTR_UNUSED static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) { - return crypto_uint64_signed_x >> (64-1); + return ct_u64_gen_mask((u64)crypto_uint64_signed_x >> (64-1)); } GCC_ATTR_UNUSED @@ -557,7 +558,7 @@ static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *c GCC_ATTR_UNUSED static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) { - return crypto_uint16_signed_x >> (16-1); + return ct_ulong_gen_mask((crypto_uint16)crypto_uint16_signed_x >> (16-1)); } GCC_ATTR_UNUSED @@ -642,7 +643,7 @@ static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *c GCC_ATTR_UNUSED static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) { - return crypto_uint32_signed_x >> (32-1); + return ct_ulong_gen_mask((crypto_uint32)crypto_uint32_signed_x >> (32-1)); } GCC_ATTR_UNUSED @@ -1484,7 +1485,7 @@ static inline uint16_t mask_nonzero(gf a) ret -= 1; ret >>= 31; - ret -= 1; + ret = ct_ulong_gen_inv_mask(ret); return ret; } @@ -1496,7 +1497,7 @@ static inline uint16_t mask_leq(uint16_t a, uint16_t b) uint32_t ret = b_tmp - a_tmp; ret >>= 31; - ret -= 1; + ret = ct_ulong_gen_inv_mask(ret); return ret; } @@ -1508,7 +1509,7 @@ static inline void vec_cmov(vec * out, vec * in, uint16_t mask) vec m0, m1; m0 = vec_set1_16b(mask); - m1 = ~m0; + m1 = vec_set1_16b((uint16_t)ct_ulong_gen_inv_mask(mask & 1)); for (i = 0; i < GFBITS; i++) { @@ -1884,8 +1885,7 @@ static void layer(int16_t *p, const unsigned char *cb, int s, int n) for (j = 0; j < stride; j++) { d = p[ i+j ] ^ p[ i+j+stride ]; - m = (cb[ index >> 3 ] >> (index & 7)) & 1; - m = -m; + m = ct_ulong_gen_mask((cb[ index >> 3 ] >> (index & 7)) & 1); d &= m; p[ i+j ] ^= d; p[ i+j+stride ] ^= d; @@ -2224,7 +2224,7 @@ static void gen_e(unsigned char *e) mask = i ^ (ind[j] >> 6); mask -= 1; mask >>= 63; - mask = -mask; + mask = ct_u64_gen_mask(mask); e_int[i] |= val[j] & mask; } @@ -2799,7 +2799,7 @@ gf gf_mul(gf in0, gf in1) t0 = in0; t1 = in1; - tmp = t0 * (t1 & 1); + tmp = t0 & ct_u64_gen_mask(t1 & 1); for (i = 1; i < GFBITS; i++) tmp ^= (t0 * (t1 & (1 << i))); @@ -3241,7 +3241,7 @@ static inline uint64_t same_mask(uint16_t x, uint16_t y) mask = x ^ y; mask -= 1; mask >>= 63; - mask = -mask; + mask = ct_u64_gen_mask(mask); return mask; } @@ -3408,7 +3408,7 @@ static int pk_gen_mat(unsigned char * pk, const unsigned char * irr, uint32_t * { mask = mat[ row ][ i ] >> j; mask &= 1; - mask -= 1; + mask = ct_u64_gen_inv_mask(mask); for (c = 0; c < nblocks_H; c++) mat[ row ][ c ] ^= mat[ k ][ c ] & mask; @@ -3423,7 +3423,7 @@ static int pk_gen_mat(unsigned char * pk, const unsigned char * irr, uint32_t * { mask = mat[ k ][ i ] >> j; mask &= 1; - mask = -mask; + mask = ct_u64_gen_mask(mask); for (c = 0; c < nblocks_H; c++) mat[ k ][ c ] ^= mat[ row ][ c ] & mask; @@ -3433,7 +3433,7 @@ static int pk_gen_mat(unsigned char * pk, const unsigned char * irr, uint32_t * { mask = mat[ k ][ i ] >> j; mask &= 1; - mask = -mask; + mask = ct_u64_gen_mask(mask); for (c = 0; c < nblocks_H; c++) mat[ k ][ c ] ^= mat[ row ][ c ] & mask; diff --git a/src/const-time.h b/src/const-time.h index c2acbb73..03a47d65 100644 --- a/src/const-time.h +++ b/src/const-time.h @@ -114,6 +114,7 @@ unsigned int _gcry_ct_memequal (const void *b1, const void *b2, size_t len); DEFINE_CT_TYPE_GEN_MASK(uintptr, uintptr_t) DEFINE_CT_TYPE_GEN_MASK(ulong, unsigned long) DEFINE_CT_TYPE_GEN_MASK(int16, int16_t) +DEFINE_CT_TYPE_GEN_MASK(u64, u64) /* * Return all bits set if A is 0 and return 1 otherwise. @@ -139,6 +140,7 @@ DEFINE_CT_TYPE_GEN_MASK(int16, int16_t) DEFINE_CT_TYPE_GEN_INV_MASK(uintptr, uintptr_t) DEFINE_CT_TYPE_GEN_INV_MASK(ulong, unsigned long) DEFINE_CT_TYPE_GEN_INV_MASK(int16, int16_t) +DEFINE_CT_TYPE_GEN_INV_MASK(u64, u64) /* * Return A when OP_ENABLED=1 @@ -155,6 +157,7 @@ DEFINE_CT_TYPE_GEN_INV_MASK(int16, int16_t) DEFINE_CT_TYPE_SELECT_FUNC(uintptr, uintptr_t) DEFINE_CT_TYPE_SELECT_FUNC(ulong, unsigned long) DEFINE_CT_TYPE_SELECT_FUNC(int16, int16_t) +DEFINE_CT_TYPE_SELECT_FUNC(u64, u64) /* * Return NULL when OP_ENABLED=1 -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 27 09:54:18 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 10:54:18 +0300 Subject: [PATCH 09/10] mceliece6688128f: update generation script to apply changes as patch set In-Reply-To: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> References: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> Message-ID: <20250927075419.1923877-9-jussi.kivilinna@iki.fi> * cipher/mceliece6688128f-patches: New. * cipher/mceliece6688128f.sh: Apply patches from 'cipher/mceliece6688128f-patches/*'. -- Signed-off-by: Jussi Kivilinna --- ...ece6688128f-fix-UBSAN-runtime-errors.patch | 135 +++++++++++++ ...-harden-mask-generation-against-bran.patch | 179 ++++++++++++++++++ ...-use-const-time-helper-for-memory-co.patch | 36 ++++ ...-fix-stack-overflow-crash-on-win64-w.patch | 71 +++++++ cipher/mceliece6688128f.sh | 19 ++ 5 files changed, 440 insertions(+) create mode 100644 cipher/mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch create mode 100644 cipher/mceliece6688128f-patches/0002-mceliece6688128f-harden-mask-generation-against-bran.patch create mode 100644 cipher/mceliece6688128f-patches/0003-mceliece6688128f-use-const-time-helper-for-memory-co.patch create mode 100644 cipher/mceliece6688128f-patches/0004-mceliece6688128f-fix-stack-overflow-crash-on-win64-w.patch diff --git a/cipher/mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch b/cipher/mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch new file mode 100644 index 00000000..581da04c --- /dev/null +++ b/cipher/mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch @@ -0,0 +1,135 @@ +From a786e3b6bf8cdc29aaa209b6528cf9b455677e1a Mon Sep 17 00:00:00 2001 +From: Jussi Kivilinna +Date: Mon, 22 Sep 2025 08:34:50 +0300 +Subject: [PATCH] mceliece6688128f: fix UBSAN runtime errors + +* cipher/mceliece6688128f.c (cbrecursion): Fix left shift of signed integer +by too many places, by casting to unsigned integer before shift. +(syndrome): Fix misaligned memory loads by using 'bufhelp.h'. +-- + +There was multiple undefined behaviour sanitizer warnings with mceliece668128f +which have been fixed by this commit: + + $ tests/t-kem + ../../cipher/mceliece6688128f.c:1766:37: runtime error: left shift of 73010 by 16 places cannot be represented in type 'int' + ../../cipher/mceliece6688128f.c:1769:37: runtime error: left shift of 71034 by 16 places cannot be represented in type 'int' + ../../cipher/mceliece6688128f.c:1792:39: runtime error: left shift of 72996 by 16 places cannot be represented in type 'int' + ../../cipher/mceliece6688128f.c:1800:41: runtime error: left shift of 71344 by 16 places cannot be represented in type 'int' + ../../cipher/mceliece6688128f.c:1807:43: runtime error: left shift of 68334 by 16 places cannot be represented in type 'int' + ../../cipher/mceliece6688128f.c:1834:23: runtime error: left shift of 72247 by 16 places cannot be represented in type 'int' + ../../cipher/mceliece6688128f.c:1833:19: runtime error: left shift of 136871 by 16 places cannot be represented in type 'int' + ../../cipher/mceliece6688128f.c:1781:41: runtime error: left shift of 66551 by 20 places cannot be represented in type 'int' + ../../cipher/mceliece6688128f.c:2261:15: runtime error: load of misaligned address 0x7ffd13d3ad84 for type 'const uint64_t', which requires 8 byte alignment + 0x7ffd13d3ad84: note: pointer points here + d8 7f e7 3c 61 1d b1 60 68 9b ff 4e 95 da 54 31 4b ca b9 7f e2 3b 06 a5 51 e3 7f 74 14 99 81 44 + ^ +t-kem: 70 tests done + +Signed-off-by: Jussi Kivilinna +--- + cipher/mceliece6688128f.c | 27 ++++++++++++++------------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c +index 6ad3eecb..ca1952b5 100644 +--- a/cipher/mceliece6688128f.c ++++ b/cipher/mceliece6688128f.c +@@ -131,6 +131,7 @@ + #endif + + #include "g10lib.h" ++#include "bufhelp.h" + #include "mceliece6688128f.h" + + static void +@@ -1763,10 +1764,10 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in + } + /* B = (p<<16)+c */ + +- for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ ++ for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<16)|x; /* A = (pibar<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ + +- for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ ++ for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ + + if (w <= 10) { +@@ -1778,7 +1779,7 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in + for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+p^{-1} */ + +- for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ ++ for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ + + for (x = 0;x < n;++x) { +@@ -1789,7 +1790,7 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in + } + for (x = 0;x < n;++x) B[x] &= 0x3ff; + } else { +- for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); ++ for (x = 0;x < n;++x) B[x] = ((u32)A[x]<<16)|(B[x]&0xffff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<16)+c */ +@@ -1797,14 +1798,14 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in + for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; + int32_sort(A,n); /* A = (id<<16)+p^(-1) */ + +- for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); ++ for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<16)|(B[x]&0xffff); + /* A = p^(-1)<<16+c */ + + if (i < w-2) { + for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); + /* B = (p^(-1)<<16)+p */ + int32_sort(B,n); /* B = (id<<16)+p^(-2) */ +- for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); ++ for (x = 0;x < n;++x) B[x] = ((u32)B[x]<<16)|(A[x]&0xffff); + /* B = (p^(-2)<<16)+c */ + } + +@@ -1830,8 +1831,8 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in + out[pos>>3] ^= fj<<(pos&7); + pos += step; + +- B[lx] = (A[lx]<<16)|Fx; +- B[lx+1] = (A[lx+1]<<16)|Fx1; ++ B[lx] = ((u32)A[lx]<<16)|Fx; ++ B[lx+1] = ((u32)A[lx+1]<<16)|Fx1; + } + /* B = (pi^(-1)<<16)+F */ + +@@ -2242,8 +2243,8 @@ static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e + { + uint64_t b; + +- const uint64_t *pk_ptr; +- const uint64_t *e_ptr = ((uint64_t *) (e + SYND_BYTES)); ++ const unsigned char *pk_ptr; ++ const unsigned char *e_ptr = (e + SYND_BYTES); + + int i, j; + +@@ -2254,13 +2255,13 @@ static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e + + for (i = 0; i < PK_NROWS; i++) + { +- pk_ptr = ((uint64_t *) (pk + PK_ROW_BYTES * i)); ++ pk_ptr = (pk + PK_ROW_BYTES * i); + + b = 0; + for (j = 0; j < PK_NCOLS/64; j++) +- b ^= pk_ptr[j] & e_ptr[j]; ++ b ^= buf_get_he64(&pk_ptr[j*8]) & buf_get_he64(&e_ptr[j*8]); + +- b ^= ((uint32_t *) &pk_ptr[j])[0] & ((uint32_t *) &e_ptr[j])[0]; ++ b ^= buf_get_he32(&pk_ptr[j*8]) & buf_get_he32(&e_ptr[j*8]); + + b ^= b >> 32; + b ^= b >> 16; +-- +2.48.1 + diff --git a/cipher/mceliece6688128f-patches/0002-mceliece6688128f-harden-mask-generation-against-bran.patch b/cipher/mceliece6688128f-patches/0002-mceliece6688128f-harden-mask-generation-against-bran.patch new file mode 100644 index 00000000..67a66d8b --- /dev/null +++ b/cipher/mceliece6688128f-patches/0002-mceliece6688128f-harden-mask-generation-against-bran.patch @@ -0,0 +1,179 @@ +From 414bd67219b96481bfa62673c98a650de313bca4 Mon Sep 17 00:00:00 2001 +From: Jussi Kivilinna +Date: Wed, 17 Sep 2025 19:14:02 +0300 +Subject: [PATCH] mceliece6688128f: harden mask generation against branch + optimization + +* cipher/mceliece6688128f.c (crypto_int64_negative_mask) +(crypto_int16_negative_mask, crypto_int32_negative_mask) +(crypto_uint64_signed_negative_mask, crypto_uint16_signed_negative_mask) +(crypto_uint32_signed_negative_mask, mask_nonzero, mask_leq, vec_cmov) +(layer, gen_e, gf_mul, same_mask, pk_gen): Generate masks with const-time +helper function. +-- + +Signed-off-by: Jussi Kivilinna +--- + cipher/mceliece6688128f.c | 34 +++++++++++++++++----------------- + 2 files changed, 20 insertions(+), 17 deletions(-) + +diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c +index ca1952b5..7cd04f3b 100644 +--- a/cipher/mceliece6688128f.c ++++ b/cipher/mceliece6688128f.c +@@ -132,6 +132,7 @@ + + #include "g10lib.h" + #include "bufhelp.h" ++#include "const-time.h" + #include "mceliece6688128f.h" + + static void +@@ -195,7 +196,7 @@ static void crypto_declassify(void *crypto_declassify_v,long long crypto_declass + GCC_ATTR_UNUSED + static crypto_int64 crypto_int64_negative_mask(crypto_int64 crypto_int64_x) + { +- return crypto_int64_x >> (64-1); ++ return ct_u64_gen_mask((u64)crypto_int64_x >> (64-1)); + } + + GCC_ATTR_UNUSED +@@ -287,7 +288,7 @@ static void crypto_int64_minmax(crypto_int64 *crypto_int64_a,crypto_int64 *crypt + GCC_ATTR_UNUSED + static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) + { +- return crypto_int16_x >> (16-1); ++ return ct_ulong_gen_mask((u16)crypto_int16_x >> (16-1)); + } + + GCC_ATTR_UNUSED +@@ -379,7 +380,7 @@ static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypt + GCC_ATTR_UNUSED + static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) + { +- return crypto_int32_x >> (32-1); ++ return ct_ulong_gen_mask((u32)crypto_int32_x >> (32-1)); + } + + GCC_ATTR_UNUSED +@@ -472,7 +473,7 @@ static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypt + GCC_ATTR_UNUSED + static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) + { +- return crypto_uint64_signed_x >> (64-1); ++ return ct_u64_gen_mask((u64)crypto_uint64_signed_x >> (64-1)); + } + + GCC_ATTR_UNUSED +@@ -557,7 +558,7 @@ static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *c + GCC_ATTR_UNUSED + static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) + { +- return crypto_uint16_signed_x >> (16-1); ++ return ct_ulong_gen_mask((crypto_uint16)crypto_uint16_signed_x >> (16-1)); + } + + GCC_ATTR_UNUSED +@@ -642,7 +643,7 @@ static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *c + GCC_ATTR_UNUSED + static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) + { +- return crypto_uint32_signed_x >> (32-1); ++ return ct_ulong_gen_mask((crypto_uint32)crypto_uint32_signed_x >> (32-1)); + } + + GCC_ATTR_UNUSED +@@ -1484,7 +1485,7 @@ static inline uint16_t mask_nonzero(gf a) + + ret -= 1; + ret >>= 31; +- ret -= 1; ++ ret = ct_ulong_gen_inv_mask(ret); + + return ret; + } +@@ -1496,7 +1497,7 @@ static inline uint16_t mask_leq(uint16_t a, uint16_t b) + uint32_t ret = b_tmp - a_tmp; + + ret >>= 31; +- ret -= 1; ++ ret = ct_ulong_gen_inv_mask(ret); + + return ret; + } +@@ -1508,7 +1509,7 @@ static inline void vec_cmov(vec * out, vec * in, uint16_t mask) + vec m0, m1; + + m0 = vec_set1_16b(mask); +- m1 = ~m0; ++ m1 = vec_set1_16b((uint16_t)ct_ulong_gen_inv_mask(mask & 1)); + + for (i = 0; i < GFBITS; i++) + { +@@ -1884,8 +1885,7 @@ static void layer(int16_t *p, const unsigned char *cb, int s, int n) + for (j = 0; j < stride; j++) + { + d = p[ i+j ] ^ p[ i+j+stride ]; +- m = (cb[ index >> 3 ] >> (index & 7)) & 1; +- m = -m; ++ m = ct_ulong_gen_mask((cb[ index >> 3 ] >> (index & 7)) & 1); + d &= m; + p[ i+j ] ^= d; + p[ i+j+stride ] ^= d; +@@ -2224,7 +2224,7 @@ static void gen_e(unsigned char *e) + mask = i ^ (ind[j] >> 6); + mask -= 1; + mask >>= 63; +- mask = -mask; ++ mask = ct_u64_gen_mask(mask); + + e_int[i] |= val[j] & mask; + } +@@ -2799,7 +2799,7 @@ gf gf_mul(gf in0, gf in1) + t0 = in0; + t1 = in1; + +- tmp = t0 * (t1 & 1); ++ tmp = t0 & ct_u64_gen_mask(t1 & 1); + + for (i = 1; i < GFBITS; i++) + tmp ^= (t0 * (t1 & (1 << i))); +@@ -3241,7 +3241,7 @@ static inline uint64_t same_mask(uint16_t x, uint16_t y) + mask = x ^ y; + mask -= 1; + mask >>= 63; +- mask = -mask; ++ mask = ct_u64_gen_mask(mask); + + return mask; + } +@@ -3409,7 +3409,7 @@ static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm + { + mask = mat[ row ][ i ] >> j; + mask &= 1; +- mask -= 1; ++ mask = ct_u64_gen_inv_mask(mask); + + for (c = 0; c < nblocks_H; c++) + mat[ row ][ c ] ^= mat[ k ][ c ] & mask; +@@ -3424,7 +3424,7 @@ static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm + { + mask = mat[ k ][ i ] >> j; + mask &= 1; +- mask = -mask; ++ mask = ct_u64_gen_mask(mask); + + for (c = 0; c < nblocks_H; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; +@@ -3434,7 +3434,7 @@ static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm + { + mask = mat[ k ][ i ] >> j; + mask &= 1; +- mask = -mask; ++ mask = ct_u64_gen_mask(mask); + + for (c = 0; c < nblocks_H; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; +-- +2.48.1 + diff --git a/cipher/mceliece6688128f-patches/0003-mceliece6688128f-use-const-time-helper-for-memory-co.patch b/cipher/mceliece6688128f-patches/0003-mceliece6688128f-use-const-time-helper-for-memory-co.patch new file mode 100644 index 00000000..d254b666 --- /dev/null +++ b/cipher/mceliece6688128f-patches/0003-mceliece6688128f-use-const-time-helper-for-memory-co.patch @@ -0,0 +1,36 @@ +From dafc2c4d839d8bc4a52b9c7a46dac9700c88853a Mon Sep 17 00:00:00 2001 +From: Jussi Kivilinna +Date: Wed, 17 Sep 2025 20:11:29 +0300 +Subject: [PATCH] mceliece6688128f: use const-time helper for memory comparison + +* cipher/mceliece6688128f.c (sync_cmp): Use const-time helper for comparison. +-- + +Signed-off-by: Jussi Kivilinna +--- + cipher/mceliece6688128f.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c +index 7cd04f3b..1add63e0 100644 +--- a/cipher/mceliece6688128f.c ++++ b/cipher/mceliece6688128f.c +@@ -2053,14 +2053,7 @@ static int weight_check(unsigned char * e, vec * error) + + static uint16_t synd_cmp(vec s0[][ GFBITS ] , vec s1[][ GFBITS ]) + { +- int i, j; +- vec diff = 0; +- +- for (i = 0; i < 4; i++) +- for (j = 0; j < GFBITS; j++) +- diff |= (s0[i][j] ^ s1[i][j]); +- +- return vec_testz(diff); ++ return _gcry_ct_memequal(s0, s1, sizeof(vec) * 4 * GFBITS); + } + + /* Niederreiter decryption with the Berlekamp decoder */ +-- +2.48.1 + diff --git a/cipher/mceliece6688128f-patches/0004-mceliece6688128f-fix-stack-overflow-crash-on-win64-w.patch b/cipher/mceliece6688128f-patches/0004-mceliece6688128f-fix-stack-overflow-crash-on-win64-w.patch new file mode 100644 index 00000000..c0682596 --- /dev/null +++ b/cipher/mceliece6688128f-patches/0004-mceliece6688128f-fix-stack-overflow-crash-on-win64-w.patch @@ -0,0 +1,71 @@ +From afacc908946717332cdd1f1c014559ff72716969 Mon Sep 17 00:00:00 2001 +From: Jussi Kivilinna +Date: Fri, 26 Sep 2025 09:45:49 +0300 +Subject: [PATCH] mceliece6688128f: fix stack overflow crash on win64/wine + +* cipher/mceliece6688128f.c (pk_gen): Remove 'mat' array allocation and +rename function to ... +(pk_gen_mat): ... this. +(pk_gen): New wrapper for 'pk_gen_mat' with dynamic allocation of 'mat' +array. +-- + +Huge array allocations from stack are not always guaranteed to work on +every target platform, so avoid allocating multi-megabyte 'mat' array +from stack. + +v2: zero 'mat' array after use. + +Signed-off-by: Jussi Kivilinna +--- + cipher/mceliece6688128f.c | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c +index ca1952b5..bdc7f265 100644 +--- a/cipher/mceliece6688128f.c ++++ b/cipher/mceliece6688128f.c +@@ -3315,16 +3315,15 @@ static int mov_columns(uint64_t mat[][ (SYS_N + 63) / 64 ], int16_t * pi, uint64 + return 0; + } + +-static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm, int16_t * pi, uint64_t * pivots) +-{ +- const int nblocks_H = (SYS_N + 63) / 64; +- const int nblocks_I = (PK_NROWS + 63) / 64; ++#define nblocks_H ((SYS_N + 63) / 64) ++#define nblocks_I ((PK_NROWS + 63) / 64) + ++static int pk_gen_mat(unsigned char * pk, const unsigned char * irr, uint32_t * perm, int16_t * pi, uint64_t * pivots, ++ uint64_t mat[ PK_NROWS ][ nblocks_H ]) ++{ + int i, j, k; + int row, c; + +- uint64_t mat[ PK_NROWS ][ nblocks_H ]; +- + uint64_t mask; + + vec irr_int[2][ GFBITS ]; +@@ -3460,6 +3459,18 @@ static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm + } + + ++static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm, int16_t * pi, uint64_t * pivots) ++{ ++ /* Allocate large array from heap to avoid stack overflow crash on Win32/Wine. */ ++ unsigned int sizeof_mat = sizeof(uint64_t) * PK_NROWS * nblocks_H; ++ void *mat = xmalloc(sizeof_mat); ++ int ret = pk_gen_mat(pk, irr, perm, pi, pivots, mat); ++ wipememory(mat, sizeof_mat); ++ xfree(mat); ++ return ret; ++} ++ ++ + /* from libmceliece-20230612/crypto_kem/6688128f/vec/sk_gen.c */ + /* + This file is for secret-key generation +-- +2.48.1 + diff --git a/cipher/mceliece6688128f.sh b/cipher/mceliece6688128f.sh index 84245432..724c79bc 100755 --- a/cipher/mceliece6688128f.sh +++ b/cipher/mceliece6688128f.sh @@ -77,10 +77,18 @@ FILES=" libmceliece-20230612/include-build/crypto_declassify.h libmceliece-20230612/crypto_kem/6688128f/vec/wrap_dec.c libmceliece-20230612/crypto_kem/6688128f/vec/wrap_enc.c libmceliece-20230612/crypto_kem/6688128f/vec/wrap_keypair.c" +PATCHES="mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch + mceliece6688128f-patches/0002-mceliece6688128f-harden-mask-generation-against-bran.patch + mceliece6688128f-patches/0003-mceliece6688128f-use-const-time-helper-for-memory-co.patch + mceliece6688128f-patches/0004-mceliece6688128f-fix-stack-overflow-crash-on-win64-w.patch + " + ### set -e cd $1 +mkdir -p mceliece6688128f-tmp +( echo '/* mceliece6688128f.c - Classic McEliece for libgcrypt' echo ' * Copyright (C) 2023-2024 Simon Josefsson ' echo ' *' @@ -248,3 +256,14 @@ void mceliece6688128f_keypair(uint8_t *pk, crypto_kem_keypair((unsigned char*) pk, (unsigned char*) sk); } EOF + +) > mceliece6688128f-tmp/mceliece6688128f.c +cd mceliece6688128f-tmp +for patchfile in $PATCHES; do + patch -s -p2 < ../$patchfile +done +cd .. +cat mceliece6688128f-tmp/mceliece6688128f.c +rm mceliece6688128f-tmp/mceliece6688128f.c.orig +rm mceliece6688128f-tmp/mceliece6688128f.c +rmdir mceliece6688128f-tmp -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 27 09:54:15 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 10:54:15 +0300 Subject: [PATCH 06/10] sntrup761: use const-time helpers for memory comparison and cond move In-Reply-To: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> References: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> Message-ID: <20250927075419.1923877-6-jussi.kivilinna@iki.fi> * cipher/sntrup761.c (Ciphertexts_diff_mask): Use '_gcry_ct_not_memequal' for checking if arrays are different. (sntrup761_dec): Use '_gcry_ct_memmov_cond' for conditionally setting 'r_enc'. -- Signed-off-by: Jussi Kivilinna --- cipher/sntrup761.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cipher/sntrup761.c b/cipher/sntrup761.c index 19e4796c..e9c7d707 100644 --- a/cipher/sntrup761.c +++ b/cipher/sntrup761.c @@ -1031,12 +1031,8 @@ sntrup761_enc (unsigned char *c, unsigned char *k, const unsigned char *pk, static int Ciphertexts_diff_mask (const unsigned char *c, const unsigned char *c2) { - uint16_t differentbits = 0; int len = Ciphertexts_bytes + Confirm_bytes; - - while (len-- > 0) - differentbits |= (*c++) ^ (*c2++); - return ct_ulong_gen_mask(ct_is_not_zero(differentbits)); + return ct_ulong_gen_mask(_gcry_ct_not_memequal(c, c2, len)); } /* k = Decap(c,sk) */ @@ -1048,6 +1044,7 @@ sntrup761_dec (unsigned char *k, const unsigned char *c, const unsigned char *sk const unsigned char *cache = rho + Inputs_bytes; Inputs r; unsigned char r_enc[Inputs_bytes]; + unsigned char tmp[Inputs_bytes]; unsigned char cnew[Ciphertexts_bytes + Confirm_bytes]; int mask; int i; @@ -1056,6 +1053,7 @@ sntrup761_dec (unsigned char *k, const unsigned char *c, const unsigned char *sk Hide (cnew, r_enc, r, pk, cache); mask = Ciphertexts_diff_mask (c, cnew); for (i = 0; i < Inputs_bytes; ++i) - r_enc[i] ^= mask & (r_enc[i] ^ rho[i]); + tmp[i] = r_enc[i] ^ rho[i]; + _gcry_ct_memmov_cond (r_enc, tmp, Inputs_bytes, mask & 1); HashSession (k, 1 + mask, r_enc, c); } -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 27 09:54:17 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 10:54:17 +0300 Subject: [PATCH 08/10] mceliece6688128f: use const-time helper for memory comparison In-Reply-To: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> References: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> Message-ID: <20250927075419.1923877-8-jussi.kivilinna@iki.fi> * cipher/mceliece6688128f.c (sync_cmp): Use const-time helper for comparison. -- Signed-off-by: Jussi Kivilinna --- cipher/mceliece6688128f.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c index 4c4eb0bd..a8655672 100644 --- a/cipher/mceliece6688128f.c +++ b/cipher/mceliece6688128f.c @@ -2053,14 +2053,7 @@ static int weight_check(unsigned char * e, vec * error) static uint16_t synd_cmp(vec s0[][ GFBITS ] , vec s1[][ GFBITS ]) { - int i, j; - vec diff = 0; - - for (i = 0; i < 4; i++) - for (j = 0; j < GFBITS; j++) - diff |= (s0[i][j] ^ s1[i][j]); - - return vec_testz(diff); + return _gcry_ct_memequal(s0, s1, sizeof(vec) * 4 * GFBITS); } /* Niederreiter decryption with the Berlekamp decoder */ -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 27 09:54:19 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 10:54:19 +0300 Subject: [PATCH 10/10] const-time: add 64-bit fast paths for const-time buffer functions In-Reply-To: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> References: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> Message-ID: <20250927075419.1923877-10-jussi.kivilinna@iki.fi> * src/const-time.c (_gcry_ct_not_memequal, _gcry_ct_memequal): Add 64-bit processing for larger than 7 byte inputs. -- Signed-off-by: Jussi Kivilinna --- src/const-time.c | 70 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/src/const-time.c b/src/const-time.c index 0fb53a07..917170fc 100644 --- a/src/const-time.c +++ b/src/const-time.c @@ -22,6 +22,7 @@ #include #include "g10lib.h" #include "const-time.h" +#include "../cipher/bufhelp.h" #ifndef HAVE_GCC_ASM_VOLATILE_MEMORY @@ -42,19 +43,46 @@ _gcry_ct_not_memequal (const void *b1, const void *b2, size_t len) { const byte *a = b1; const byte *b = b2; - int ab, ba; - size_t i; + u32 ab = 0; + u32 ba = 0; /* Constant-time compare. */ - for (i = 0, ab = 0, ba = 0; i < len; i++) + + if (len >= sizeof(u64)) + { + u64 ab8 = 0; + u64 ba8 = 0; + + while (len >= sizeof(u64)) + { + u64 a8 = buf_get_he64 (a); + u64 b8 = buf_get_he64 (b); + + /* If a8 != b8, either ab8 or ba8 will have high bit set. */ + ab8 |= a8 - b8; + ba8 |= b8 - a8; + + a += sizeof(u64); + b += sizeof(u64); + len -= sizeof(u64); + } + + ab = ct_u64_gen_mask ((ab8 >> (sizeof(u64) * 8 - 1)) & 1); + ba = ct_u64_gen_mask ((ba8 >> (sizeof(u64) * 8 - 1)) & 1); + } + + while (len > 0) { - /* If a[i] != b[i], either ab or ba will be negative. */ - ab |= a[i] - b[i]; - ba |= b[i] - a[i]; + /* If *a != *b, either ab or ba will have high bit set. */ + ab |= *a - *b; + ba |= *b - *a; + a++; + b++; + len--; } - /* 'ab | ba' is negative when buffers are not equal, extract sign bit. */ - return ((unsigned int)(ab | ba) >> (sizeof(unsigned int) * 8 - 1)) & 1; + /* 'ab | ba' has high bit set when buffers are not equal. */ + return ((ab | ba) >> (sizeof(u32) * 8 - 1)) & 1; } /* @@ -77,12 +105,28 @@ _gcry_ct_memmov_cond (void *dst, const void *src, size_t len, unsigned long op_enable) { /* Note: dual mask with AND/OR used for EM leakage mitigation */ - unsigned char mask1 = ct_ulong_gen_mask(op_enable); - unsigned char mask2 = ct_ulong_gen_inv_mask(op_enable); + u64 mask1 = ct_u64_gen_mask (op_enable); + u64 mask2 = ct_u64_gen_inv_mask (op_enable); unsigned char *b_dst = dst; const unsigned char *b_src = src; - size_t i; - for (i = 0; i < len; i++) - b_dst[i] = (b_dst[i] & mask2) | (b_src[i] & mask1); + while (len >= sizeof(u64)) + { + u64 dst8 = buf_get_he64 (b_dst); + u64 src8 = buf_get_he64 (b_src); + + buf_put_he64 (b_dst, (dst8 & mask2) | (src8 & mask1)); + + b_dst += sizeof(u64); + b_src += sizeof(u64); + len -= sizeof(u64); + } + + while (len > 0) + { + *b_dst = (*b_dst & mask2) | (*b_src & mask1); + b_dst++; + b_src++; + len--; + } } -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 27 09:54:11 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 10:54:11 +0300 Subject: [PATCH 02/10] cipher-xts: harden mask generation against branch optimization In-Reply-To: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> References: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> Message-ID: <20250927075419.1923877-2-jussi.kivilinna@iki.fi> * cipher/cipher-xts.c (xts_gfmul_byA): Generate mask with const-time helper. -- Signed-off-by: Jussi Kivilinna --- cipher/cipher-xts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cipher/cipher-xts.c b/cipher/cipher-xts.c index 754f289c..6c684263 100644 --- a/cipher/cipher-xts.c +++ b/cipher/cipher-xts.c @@ -33,7 +33,7 @@ static inline void xts_gfmul_byA (unsigned char *out, const unsigned char *in) { u64 hi = buf_get_le64 (in + 8); u64 lo = buf_get_le64 (in + 0); - u64 carry = -(hi >> 63) & 0x87; + u64 carry = ct_ulong_gen_mask(hi >> 63) & 0x87; hi = (hi << 1) + (lo >> 63); lo = (lo << 1) ^ carry; -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 27 09:54:13 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 10:54:13 +0300 Subject: [PATCH 04/10] kyber: harden mask generation against branch optimization In-Reply-To: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> References: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> Message-ID: <20250927075419.1923877-4-jussi.kivilinna@iki.fi> * cipher/kyber-kdep.c (polyvec_compress, polyvec_compress): Generate mask with const-time helper function. -- Signed-off-by: Jussi Kivilinna --- cipher/kyber-kdep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cipher/kyber-kdep.c b/cipher/kyber-kdep.c index e97e0c45..2fc0ea7b 100644 --- a/cipher/kyber-kdep.c +++ b/cipher/kyber-kdep.c @@ -571,7 +571,7 @@ void polyvec_compress(uint8_t r[KYBER_POLYVECCOMPRESSEDBYTES], const polyvec *a) for(j=0;jvec[i].coeffs[8*j+k]; - t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; + t[k] += ct_ulong_gen_mask((uint16_t)t[k] >> 15) & KYBER_Q; /* t[k] = ((((uint32_t)t[k] << 11) + KYBER_Q/2)/KYBER_Q) & 0x7ff; */ d0 = t[k]; d0 <<= 11; @@ -602,7 +602,7 @@ void polyvec_compress(uint8_t r[KYBER_POLYVECCOMPRESSEDBYTES], const polyvec *a) for(j=0;jvec[i].coeffs[4*j+k]; - t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; + t[k] += ct_ulong_gen_mask((uint16_t)t[k] >> 15) & KYBER_Q; /* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */ d0 = t[k]; d0 <<= 10; -- 2.48.1 From jussi.kivilinna at iki.fi Sat Sep 27 11:52:24 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 27 Sep 2025 12:52:24 +0300 Subject: [PATCH] Add stack burning for PQC algorithms Message-ID: <20250927095224.2362510-1-jussi.kivilinna@iki.fi> * cipher/dilithium.h (DILITHIUM_KEYPAIR_STACK_BURN) (DILITHIUM_SIGN_STACK_BURN, DILITHIUM_VERIFY_STACK_BURN): New. * cipher/kem.c (_gcry_kem_genkey, _gcry_kem_encap) (_gcry_kem_decap): Burn stack after calls to sntrup761, kyber and mceliece6688128f algos. * cipher/kyber.h (KYBER_KEYPAIR_STACK_BURN, KYBER_ENCAP_STACK_BURN) (KYBER_DECAP_STACK_BURN): New. * cipher/mceliece6688128f.h (MCELIECE6688128F_KEYPAIR_STACK_BURN) (MCELIECE6688128F_ENC_STACK_BURN, MCELIECE6688128F_DEC_STACK_BURN): New. * cipher/pubkey-dilithium.c (mldsa_generate, mldsa_sign) (mldsa_verify): Burn stack after calls to dilithium algo. * cipher/sntrup761.h (SNTRUP761_KEYPAIR_STACK_BURN) (SNTRUP761_ENC_STACK_BURN, SNTRUP761_DEC_STACK_BURN): New. -- Stack usage measured on GCC-14 build on x86-64/linux with additional +33% margin added and rounded up to closest 1 KiB. Signed-off-by: Jussi Kivilinna --- cipher/dilithium.h | 4 ++++ cipher/kem.c | 11 +++++++++++ cipher/kyber.h | 13 +++++++++++++ cipher/mceliece6688128f.h | 4 ++++ cipher/pubkey-dilithium.c | 3 +++ cipher/sntrup761.h | 4 ++++ 6 files changed, 39 insertions(+) diff --git a/cipher/dilithium.h b/cipher/dilithium.h index 03a095c7..88a48094 100644 --- a/cipher/dilithium.h +++ b/cipher/dilithium.h @@ -60,6 +60,10 @@ #define dilithium_decap _gcry_mldsa_decap /**** End of the glue code ****/ +#define DILITHIUM_KEYPAIR_STACK_BURN (128 * 1024) +#define DILITHIUM_SIGN_STACK_BURN (161 * 1024) +#define DILITHIUM_VERIFY_STACK_BURN (122 * 1024) + int dilithium_keypair (int algo, uint8_t *pk, uint8_t *sk, const uint8_t seed[SEEDBYTES]); int dilithium_sign (int algo, uint8_t *sig, size_t siglen, diff --git a/cipher/kem.c b/cipher/kem.c index 072249e2..2a432a0a 100644 --- a/cipher/kem.c +++ b/cipher/kem.c @@ -96,10 +96,12 @@ _gcry_kem_genkey (int algo, || pubkey_len != GCRY_KEM_SNTRUP761_PUBKEY_LEN) return GPG_ERR_INV_ARG; sntrup761_keypair (pubkey, seckey, NULL, sntrup761_random); + _gcry_burn_stack (SNTRUP761_KEYPAIR_STACK_BURN); return 0; case GCRY_KEM_CM6688128F: mceliece6688128f_keypair (pubkey, seckey); + _gcry_burn_stack (MCELIECE6688128F_KEYPAIR_STACK_BURN); return 0; #if USE_KYBER @@ -109,6 +111,7 @@ _gcry_kem_genkey (int algo, || (optional && optional_len != GCRY_KEM_MLKEM_RANDOM_LEN*2)) return GPG_ERR_INV_ARG; kyber_keypair (algo, pubkey, seckey, optional); + _gcry_burn_stack (KYBER_KEYPAIR_STACK_BURN (algo)); return 0; case GCRY_KEM_MLKEM768: @@ -117,6 +120,7 @@ _gcry_kem_genkey (int algo, || (optional && optional_len != GCRY_KEM_MLKEM_RANDOM_LEN*2)) return GPG_ERR_INV_ARG; kyber_keypair (algo, pubkey, seckey, optional); + _gcry_burn_stack (KYBER_KEYPAIR_STACK_BURN (algo)); return 0; case GCRY_KEM_MLKEM1024: @@ -125,6 +129,7 @@ _gcry_kem_genkey (int algo, || (optional && optional_len != GCRY_KEM_MLKEM_RANDOM_LEN*2)) return GPG_ERR_INV_ARG; kyber_keypair (algo, pubkey, seckey, optional); + _gcry_burn_stack (KYBER_KEYPAIR_STACK_BURN (algo)); return 0; #endif @@ -166,12 +171,14 @@ _gcry_kem_encap (int algo, || shared_len != GCRY_KEM_SNTRUP761_SHARED_LEN) return GPG_ERR_INV_VALUE; sntrup761_enc (ciphertext, shared, pubkey, NULL, sntrup761_random); + _gcry_burn_stack (SNTRUP761_ENC_STACK_BURN); return 0; case GCRY_KEM_CM6688128F: if (optional != NULL) return GPG_ERR_INV_VALUE; mceliece6688128f_enc (ciphertext, shared, pubkey); + _gcry_burn_stack (MCELIECE6688128F_ENC_STACK_BURN); return 0; #if USE_KYBER @@ -181,6 +188,7 @@ _gcry_kem_encap (int algo, if (optional && optional_len != GCRY_KEM_MLKEM_RANDOM_LEN) return GPG_ERR_INV_VALUE; kyber_encap (algo, ciphertext, shared, pubkey, optional); + _gcry_burn_stack (KYBER_ENCAP_STACK_BURN (algo)); return 0; #endif @@ -228,12 +236,14 @@ _gcry_kem_decap (int algo, || shared_len != GCRY_KEM_SNTRUP761_SHARED_LEN) return GPG_ERR_INV_VALUE; sntrup761_dec (shared, ciphertext, seckey); + _gcry_burn_stack (SNTRUP761_DEC_STACK_BURN); return 0; case GCRY_KEM_CM6688128F: if (optional != NULL) return GPG_ERR_INV_VALUE; mceliece6688128f_dec (shared, ciphertext, seckey); + _gcry_burn_stack (MCELIECE6688128F_DEC_STACK_BURN); return 0; #if USE_KYBER @@ -243,6 +253,7 @@ _gcry_kem_decap (int algo, if (optional != NULL) return GPG_ERR_INV_VALUE; kyber_decap (algo, shared, ciphertext, seckey); + _gcry_burn_stack (KYBER_DECAP_STACK_BURN (algo)); return 0; #endif diff --git a/cipher/kyber.h b/cipher/kyber.h index b1ba0eab..0ef2eb65 100644 --- a/cipher/kyber.h +++ b/cipher/kyber.h @@ -60,6 +60,19 @@ #define kyber_decap _gcry_mlkem_decap /**** End of the glue code ****/ +#define KYBER_KEYPAIR_STACK_BURN(algo) \ + ((algo) == GCRY_KEM_MLKEM512 ? (9 * 1024) : \ + (algo) == GCRY_KEM_MLKEM768 ? (15 * 1024) : \ + /* MLKEM1024*/ (21 * 1024)) +#define KYBER_ENCAP_STACK_BURN(algo) \ + ((algo) == GCRY_KEM_MLKEM512 ? (13 * 1024) : \ + (algo) == GCRY_KEM_MLKEM768 ? (19 * 1024) : \ + /* MLKEM1024*/ (26 * 1024)) +#define KYBER_DECAP_STACK_BURN(algo) \ + ((algo) == GCRY_KEM_MLKEM512 ? (18 * 1024) : \ + (algo) == GCRY_KEM_MLKEM768 ? (25 * 1024) : \ + /* MLKEM1024*/ (35 * 1024)) + void kyber_keypair (int algo, uint8_t *pk, uint8_t *sk, const uint8_t *coins); void kyber_encap (int algo, uint8_t *ct, uint8_t *ss, const uint8_t *pk, const uint8_t *coins); diff --git a/cipher/mceliece6688128f.h b/cipher/mceliece6688128f.h index eb9f23a0..4b1b35c9 100644 --- a/cipher/mceliece6688128f.h +++ b/cipher/mceliece6688128f.h @@ -30,6 +30,10 @@ #include "g10lib.h" /* for GCC_ATTR_UNUSED */ #include "gcrypt-int.h" +#define MCELIECE6688128F_KEYPAIR_STACK_BURN (360 * 1024) +#define MCELIECE6688128F_ENC_STACK_BURN (9 * 1024) +#define MCELIECE6688128F_DEC_STACK_BURN (80 * 1024) + #define mceliece6688128f_keypair _gcry_mceliece6688128f_keypair #define mceliece6688128f_enc _gcry_mceliece6688128f_enc #define mceliece6688128f_dec _gcry_mceliece6688128f_dec diff --git a/cipher/pubkey-dilithium.c b/cipher/pubkey-dilithium.c index 7f87a99f..03958bb0 100644 --- a/cipher/pubkey-dilithium.c +++ b/cipher/pubkey-dilithium.c @@ -171,6 +171,7 @@ mldsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) } dilithium_keypair (info->algo, pk, sk, seed); + _gcry_burn_stack (DILITHIUM_KEYPAIR_STACK_BURN); if (!rc) rc = sexp_build (r_skey, @@ -262,6 +263,7 @@ mldsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) else r = dilithium_sign (info->algo, sig, info->sig_len, data, data_len, ctx.label, ctx.labellen, sk, rnd); + _gcry_burn_stack (DILITHIUM_SIGN_STACK_BURN); if (r < 0) { rc = GPG_ERR_INTERNAL; @@ -353,6 +355,7 @@ mldsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) else r = dilithium_verify (info->algo, sig, info->sig_len, data, data_len, ctx.label, ctx.labellen, pk); + _gcry_burn_stack (DILITHIUM_VERIFY_STACK_BURN); if (r < 0) { rc = GPG_ERR_BAD_SIGNATURE; diff --git a/cipher/sntrup761.h b/cipher/sntrup761.h index a9974bb0..88f7a902 100644 --- a/cipher/sntrup761.h +++ b/cipher/sntrup761.h @@ -46,6 +46,10 @@ crypto_hash_sha512 (unsigned char *out, _gcry_md_hash_buffer (GCRY_MD_SHA512, out, in, inlen); } +#define SNTRUP761_KEYPAIR_STACK_BURN (26 * 1024) +#define SNTRUP761_ENC_STACK_BURN (23 * 1024) +#define SNTRUP761_DEC_STACK_BURN (34 * 1024) + #define sntrup761_keypair _gcry_sntrup761_keypair #define sntrup761_enc _gcry_sntrup761_enc #define sntrup761_dec _gcry_sntrup761_dec -- 2.48.1 From jcb62281 at gmail.com Sun Sep 28 03:33:01 2025 From: jcb62281 at gmail.com (Jacob Bachmeyer) Date: Sat, 27 Sep 2025 20:33:01 -0500 Subject: [PATCH v2] mceliece6688128f: fix stack overflow crash on win64/wine In-Reply-To: <20250927070254.1705049-1-jussi.kivilinna@iki.fi> References: <20250927070254.1705049-1-jussi.kivilinna@iki.fi> Message-ID: On 9/27/25 02:02, Jussi Kivilinna wrote: > * cipher/mceliece6688128f.c (pk_gen): Remove 'mat' array allocation and > rename function to ... > (pk_gen_mat): ... this. > (pk_gen): New wrapper for 'pk_gen_mat' with dynamic allocation of 'mat' > array. > -- > > Huge array allocations from stack are not always guaranteed to work on > every target platform, so avoid allocating multi-megabyte 'mat' array > from stack. > > v2: zero 'mat' array after use. > > Signed-off-by: Jussi Kivilinna > --- > cipher/mceliece6688128f.c | 23 +++++++++++++++++------ > 1 file changed, 17 insertions(+), 6 deletions(-) > > diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c > index ca1952b5..bdc7f265 100644 > --- a/cipher/mceliece6688128f.c > +++ b/cipher/mceliece6688128f.c > [...] > @@ -3460,6 +3459,18 @@ static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm > } > > > +static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm, int16_t * pi, uint64_t * pivots) > +{ > + /* Allocate large array from heap to avoid stack overflow crash on Win32/Wine. */ > + unsigned int sizeof_mat = sizeof(uint64_t) * PK_NROWS * nblocks_H; Would this make sense as "const unsigned int sizeof_mat" to enable better compiler optimizations/inlining since PK_NROWS and nblocks_H seem to be constants?? Or is GCC able to deduce that sizeof_mat is only assigned once? Also, would "size_t" be a more appropriate base type than unsigned int, yielding "const size_t sizeof_mat = [...]"? > + void *mat = xmalloc(sizeof_mat); > + int ret = pk_gen_mat(pk, irr, perm, pi, pivots, mat); > + wipememory(mat, sizeof_mat); > + xfree(mat); > + return ret; > +} > + > + > /* from libmceliece-20230612/crypto_kem/6688128f/vec/sk_gen.c */ > /* > This file is for secret-key generation -- Jacob From jcb62281 at gmail.com Sun Sep 28 03:37:58 2025 From: jcb62281 at gmail.com (Jacob Bachmeyer) Date: Sat, 27 Sep 2025 20:37:58 -0500 Subject: [PATCH 1/2] mceliece6688128f: fix stack overflow crash on win64/wine In-Reply-To: References: <20250926065302.1693112-1-jussi.kivilinna@iki.fi> <437e0196-6a62-4a11-bc14-5420c7a05d97@gmail.com> Message-ID: <0c71d8fa-2763-4058-a348-8809b16f7a00@gmail.com> On 9/27/25 01:16, Jussi Kivilinna wrote: > Hello, > > [...] > > [...] About memory zeroing in general... I see that PQ algorithms use > quite a lot of stack arrays in their implementations (some quite large > allocations too) but there is no stack memory wiping in place. Maybe > there should be? I guess simplest way to wipe used stack would be to > add appropriately sized _gcry_burn_stack() calls after each PQ > function call, for example in 'kem.c'. This kind of oversight being common in PQC code is *not* reassuring when the appropriate paranoia has long been standard in RSA implementations. -- Jacob From jussi.kivilinna at iki.fi Sun Sep 28 09:56:43 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 28 Sep 2025 10:56:43 +0300 Subject: [PATCH v2] mceliece6688128f: fix stack overflow crash on win64/wine In-Reply-To: References: <20250927070254.1705049-1-jussi.kivilinna@iki.fi> Message-ID: On 28/09/2025 04:33, Jacob Bachmeyer via Gcrypt-devel wrote: > On 9/27/25 02:02, Jussi Kivilinna wrote: >> * cipher/mceliece6688128f.c (pk_gen): Remove 'mat' array allocation and >> rename function to ... >> (pk_gen_mat): ... this. >> (pk_gen): New wrapper for 'pk_gen_mat' with dynamic allocation of 'mat' >> array. >> -- >> >> Huge array allocations from stack are not always guaranteed to work on >> every target platform, so avoid allocating multi-megabyte 'mat' array >> from stack. >> >> v2: zero 'mat' array after use. >> >> Signed-off-by: Jussi Kivilinna >> --- >> ? cipher/mceliece6688128f.c | 23 +++++++++++++++++------ >> ? 1 file changed, 17 insertions(+), 6 deletions(-) >> >> diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c >> index ca1952b5..bdc7f265 100644 >> --- a/cipher/mceliece6688128f.c >> +++ b/cipher/mceliece6688128f.c >> [...] >> @@ -3460,6 +3459,18 @@ static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm >> ? } >> +static int pk_gen(unsigned char * pk, const unsigned char * irr, uint32_t * perm, int16_t * pi, uint64_t * pivots) >> +{ >> +??? /* Allocate large array from heap to avoid stack overflow crash on Win32/Wine. */ >> +??? unsigned int sizeof_mat = sizeof(uint64_t) * PK_NROWS * nblocks_H; > > Would this make sense as "const unsigned int sizeof_mat" to enable better compiler optimizations/inlining since PK_NROWS and nblocks_H seem to be constants?? Or is GCC able to deduce that sizeof_mat is only assigned once? With GCC -O0, "unsigned int sizeof_mat" and "const unsigned int sizeof_mat" generate the same code, value is assigned to stack memory. With -O1 and above, compiler deduces that this is constant variable and optimizes as it sees best fit. 'const' on stack variables only really affects syntax checks and gives compile-time error when trying reassigning to that variable. > > Also, would "size_t" be a more appropriate base type than unsigned int, yielding "const size_t sizeof_mat = [...]"? I saw that "unsigned int" is large enough for that value, but I'll change type to "size_t" for consistency. -Jussi From jcb62281 at gmail.com Mon Sep 29 01:23:20 2025 From: jcb62281 at gmail.com (Jacob Bachmeyer) Date: Sun, 28 Sep 2025 18:23:20 -0500 Subject: [PATCH v2] mceliece6688128f: fix stack overflow crash on win64/wine In-Reply-To: References: <20250927070254.1705049-1-jussi.kivilinna@iki.fi> Message-ID: On 9/28/25 02:56, Jussi Kivilinna wrote: > On 28/09/2025 04:33, Jacob Bachmeyer via Gcrypt-devel wrote: >> [...] >> >> Would this make sense as "const unsigned int sizeof_mat" to enable >> better compiler optimizations/inlining since PK_NROWS and nblocks_H >> seem to be constants?? Or is GCC able to deduce that sizeof_mat is >> only assigned once? > > With GCC -O0, "unsigned int sizeof_mat" and "const unsigned int > sizeof_mat" generate the same code, value is assigned to stack memory. > With -O1 and above, compiler deduces that this is constant variable > and optimizes as it sees best fit. 'const' on stack variables only > really affects syntax checks and gives compile-time error when trying > reassigning to that variable. So GCC does recognize constants and optimize accordingly.? Good. Why not include the "const" as well to ensure that a compile-time error will be thrown if any future code attempts to change the value, since there is no way that such code could be correct? -- Jacob From jussi.kivilinna at iki.fi Tue Sep 30 08:30:14 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 30 Sep 2025 09:30:14 +0300 Subject: [PATCH 09/10] mceliece6688128f: update generation script to apply changes as patch set In-Reply-To: <20250927075419.1923877-9-jussi.kivilinna@iki.fi> References: <20250927075419.1923877-1-jussi.kivilinna@iki.fi> <20250927075419.1923877-9-jussi.kivilinna@iki.fi> Message-ID: Hello, On 27/09/2025 10:54, Jussi Kivilinna wrote: > * cipher/mceliece6688128f-patches: New. > * cipher/mceliece6688128f.sh: Apply patches from > 'cipher/mceliece6688128f-patches/*'. > -- I had to drop this commit with patch files as git server rejects this with: remote: cipher/mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch:40: trailing whitespace. remote: + remote: cipher/mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch:44: trailing whitespace. remote: + remote: cipher/mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch:49: trailing whitespace. remote: + <...snip...> remote: error: hook declined to update refs/heads/master Should I anyway try to wrestle this change in to repo? These patch files could be packaged into tar.gz for example. -Jussi > > Signed-off-by: Jussi Kivilinna > --- > ...ece6688128f-fix-UBSAN-runtime-errors.patch | 135 +++++++++++++ > ...-harden-mask-generation-against-bran.patch | 179 ++++++++++++++++++ > ...-use-const-time-helper-for-memory-co.patch | 36 ++++ > ...-fix-stack-overflow-crash-on-win64-w.patch | 71 +++++++ > cipher/mceliece6688128f.sh | 19 ++ > 5 files changed, 440 insertions(+) > create mode 100644 cipher/mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch > create mode 100644 cipher/mceliece6688128f-patches/0002-mceliece6688128f-harden-mask-generation-against-bran.patch > create mode 100644 cipher/mceliece6688128f-patches/0003-mceliece6688128f-use-const-time-helper-for-memory-co.patch > create mode 100644 cipher/mceliece6688128f-patches/0004-mceliece6688128f-fix-stack-overflow-crash-on-win64-w.patch > > diff --git a/cipher/mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch b/cipher/mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch > new file mode 100644 > index 00000000..581da04c > --- /dev/null > +++ b/cipher/mceliece6688128f-patches/0001-mceliece6688128f-fix-UBSAN-runtime-errors.patch > @@ -0,0 +1,135 @@ > +From a786e3b6bf8cdc29aaa209b6528cf9b455677e1a Mon Sep 17 00:00:00 2001 > +From: Jussi Kivilinna > +Date: Mon, 22 Sep 2025 08:34:50 +0300 > +Subject: [PATCH] mceliece6688128f: fix UBSAN runtime errors > + > +* cipher/mceliece6688128f.c (cbrecursion): Fix left shift of signed integer > +by too many places, by casting to unsigned integer before shift. > +(syndrome): Fix misaligned memory loads by using 'bufhelp.h'. > +-- > + > +There was multiple undefined behaviour sanitizer warnings with mceliece668128f > +which have been fixed by this commit: > + > + $ tests/t-kem > + ../../cipher/mceliece6688128f.c:1766:37: runtime error: left shift of 73010 by 16 places cannot be represented in type 'int' > + ../../cipher/mceliece6688128f.c:1769:37: runtime error: left shift of 71034 by 16 places cannot be represented in type 'int' > + ../../cipher/mceliece6688128f.c:1792:39: runtime error: left shift of 72996 by 16 places cannot be represented in type 'int' > + ../../cipher/mceliece6688128f.c:1800:41: runtime error: left shift of 71344 by 16 places cannot be represented in type 'int' > + ../../cipher/mceliece6688128f.c:1807:43: runtime error: left shift of 68334 by 16 places cannot be represented in type 'int' > + ../../cipher/mceliece6688128f.c:1834:23: runtime error: left shift of 72247 by 16 places cannot be represented in type 'int' > + ../../cipher/mceliece6688128f.c:1833:19: runtime error: left shift of 136871 by 16 places cannot be represented in type 'int' > + ../../cipher/mceliece6688128f.c:1781:41: runtime error: left shift of 66551 by 20 places cannot be represented in type 'int' > + ../../cipher/mceliece6688128f.c:2261:15: runtime error: load of misaligned address 0x7ffd13d3ad84 for type 'const uint64_t', which requires 8 byte alignment > + 0x7ffd13d3ad84: note: pointer points here > + d8 7f e7 3c 61 1d b1 60 68 9b ff 4e 95 da 54 31 4b ca b9 7f e2 3b 06 a5 51 e3 7f 74 14 99 81 44 > + ^ > +t-kem: 70 tests done > + > +Signed-off-by: Jussi Kivilinna > +--- > + cipher/mceliece6688128f.c | 27 ++++++++++++++------------- > + 1 file changed, 14 insertions(+), 13 deletions(-) > + > +diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c > +index 6ad3eecb..ca1952b5 100644 > +--- a/cipher/mceliece6688128f.c > ++++ b/cipher/mceliece6688128f.c > +@@ -131,6 +131,7 @@ > + #endif > + > + #include "g10lib.h" > ++#include "bufhelp.h" > + #include "mceliece6688128f.h" > + > + static void > +@@ -1763,10 +1764,10 @@ static void cbrecursion(unsigned char *out,long long pos,long long step,const in > + } > + /* B = (p<<16)+c */ > + > +- for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ > ++ for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<16)|x; /* A = (pibar<<16)+id */ > + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ > + > +- for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ > ++ for (x = 0;x < n;++x) A[x] = ((u32)A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ > + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ > +