From gniibe at fsij.org Mon Feb 3 01:31:20 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Mon, 03 Feb 2025 09:31:20 +0900 Subject: [PATCH] MPI helper of multiplication, Least Leak Intended In-Reply-To: <877c6b8pp8.fsf@akagi.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> Message-ID: <87seovj2cn.fsf@akagi.fsij.org> NIIBE Yutaka wrote: > Honestly speaking, it's "Least Leak Intended", and I couldn't declare > it constant-time. I pushed the change for _gcry_mpih_mul_lli. And I also pushed the change for _gcry_mpih_mod_lli. The implementation was already there, it's renaming _gcry_mpih_mod_lli from _gcry_mpih_mod. -- From jussi.kivilinna at iki.fi Mon Feb 3 20:22:07 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 3 Feb 2025 21:22:07 +0200 Subject: [PATCH 1/3] t-fips-service-ind: fix broken fail print Message-ID: <20250203192209.3072952-1-jussi.kivilinna@iki.fi> * tests/t-fips-service-ind.c (check_cipher_o_s_e_d_c): Fix typo '<' to ','. -- Signed-off-by: Jussi Kivilinna --- tests/t-fips-service-ind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/t-fips-service-ind.c b/tests/t-fips-service-ind.c index 74521bb3..ed5f8d3f 100644 --- a/tests/t-fips-service-ind.c +++ b/tests/t-fips-service-ind.c @@ -767,7 +767,7 @@ check_cipher_o_s_e_d_c (int reject) err = gcry_cipher_set_decryption_tag (h, tag, 16); if (err) - fail ("gcry_cipher_set_decryption_tag %d failed: %s\n", tvidx< + fail ("gcry_cipher_set_decryption_tag %d failed: %s\n", tvidx, gpg_strerror (err)); } -- 2.45.2 From jussi.kivilinna at iki.fi Mon Feb 3 20:22:08 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 3 Feb 2025 21:22:08 +0200 Subject: [PATCH 2/3] mpih-const-time: avoid branches in _gcry_mpih_cmp_ui In-Reply-To: <20250203192209.3072952-1-jussi.kivilinna@iki.fi> References: <20250203192209.3072952-1-jussi.kivilinna@iki.fi> Message-ID: <20250203192209.3072952-2-jussi.kivilinna@iki.fi> * mpi/mpih-const-time.c (_gcry_mpih_cmp_ui): Avoid conditional branches for return value selection. -- Signed-off-by: Jussi Kivilinna --- mpi/mpih-const-time.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/mpi/mpih-const-time.c b/mpi/mpih-const-time.c index e684b956..d8b66c46 100644 --- a/mpi/mpih-const-time.c +++ b/mpi/mpih-const-time.c @@ -222,20 +222,15 @@ _gcry_mpih_mod_lli (mpi_ptr_t vp, mpi_size_t vsize, int _gcry_mpih_cmp_ui (mpi_ptr_t up, mpi_size_t usize, unsigned long v) { - int is_all_zero = 1; + unsigned long is_all_zero = ct_ulong_gen_mask(1); + int cmp0; mpi_size_t i; + cmp0 = -mpih_ct_limb_less_than (up[0], v); + cmp0 |= mpih_ct_limb_greater_than (up[0], v); + for (i = 1; i < usize; i++) - is_all_zero &= mpih_limb_is_zero (up[i]); + is_all_zero &= ct_ulong_gen_mask(mpih_limb_is_zero (up[i])); - if (is_all_zero) - { - if (up[0] < v) - return -1; - else if (up[0] > v) - return 1; - else - return 0; - } - return 1; + return cmp0 & (int)is_all_zero; } -- 2.45.2 From jussi.kivilinna at iki.fi Mon Feb 3 20:22:09 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 3 Feb 2025 21:22:09 +0200 Subject: [PATCH 3/3] mpi/longlong: prevent optimization of carry instructions to branches In-Reply-To: <20250203192209.3072952-1-jussi.kivilinna@iki.fi> References: <20250203192209.3072952-1-jussi.kivilinna@iki.fi> Message-ID: <20250203192209.3072952-3-jussi.kivilinna@iki.fi> * mpi/longlong.h: Include "const-time.h" (add_ssaaaa, sub_ddmmss): Prevent optimization of carry handling to conditional branches in generic variant of double width addition and subtraction as was seen with GCC on riscv64. (umul_ppmm): Avoid conditional branch in generic 16x16=>32bit multiplication version of umul_ppmm. * src/const-time.h (CT_DEOPTIMIZE_VAR): New. -- RISC-V has "sltu" instruction for generating carry value and generic version of add_ssaaaa and sub_ddmmss typically used this instruction. However, sometimes compiler gets too clever and instead generates code with conditional branch, which is not good for constant time code. Commit changes add_ssaaaaa and sub_ddmmss to clobber high word of calculation in a way that prevents such optimizations. Signed-off-by: Jussi Kivilinna --- mpi/longlong.h | 47 +++++++++++++++++++++++++++++++---------------- src/const-time.h | 8 ++++++++ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/mpi/longlong.h b/mpi/longlong.h index 21bd1a7e..7dc67591 100644 --- a/mpi/longlong.h +++ b/mpi/longlong.h @@ -20,6 +20,8 @@ along with this file; see the file COPYING.LIB. If not, see > W_TYPE_SIZE); \ - (sl) = (UWtype)(__audw); \ + __auwh = (UWtype)(__audw >> W_TYPE_SIZE); \ + __auwl = (UWtype)(__audw); \ + CT_DEOPTIMIZE_VAR(__auwh); \ + (sh) = __auwh; \ + (sl) = __auwl; \ } while (0) #elif !defined (add_ssaaaa) # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ do { \ - UWtype __x; \ - __x = (al) + (bl); \ - (sh) = (ah) + (bh) + (__x < (al)); \ - (sl) = __x; \ + UWtype __xl, __xh; \ + __xl = (al) + (bl); \ + __xh = __xl < (al); \ + __xh = (ah) + (bh) + __xh; \ + CT_DEOPTIMIZE_VAR(__xh); \ + (sh) = __xh; \ + (sl) = __xl; \ } while (0) #endif @@ -1606,22 +1615,29 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ do { \ UDWtype __audw = (ah); \ + UWtype __auwh, __auwl; \ UDWtype __budw = (bh); \ __audw <<= W_TYPE_SIZE; \ __audw |= (al); \ __budw <<= W_TYPE_SIZE; \ __budw |= (bl); \ __audw -= __budw; \ - (sh) = (UWtype)(__audw >> W_TYPE_SIZE); \ - (sl) = (UWtype)(__audw); \ + __auwh = (UWtype)(__audw >> W_TYPE_SIZE); \ + __auwl = (UWtype)(__audw); \ + CT_DEOPTIMIZE_VAR(__auwh); \ + (sh) = __auwh; \ + (sl) = __auwl; \ } while (0) #elif !defined (sub_ddmmss) # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ do { \ - UWtype __x; \ - __x = (al) - (bl); \ - (sh) = (ah) - (bh) - (__x > (al)); \ - (sl) = __x; \ + UWtype __xl, __xh; \ + __xl = (al) - (bl); \ + __xh = (__xl > (al)); \ + __xh = (ah) - (bh) - __xh; \ + CT_DEOPTIMIZE_VAR(__xh); \ + (sh) = __xh; \ + (sl) = __xl; \ } while (0) #endif @@ -1651,10 +1667,9 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); __x3 = (UWtype) __uh * __vh; \ \ __x1 += __ll_highpart (__x0);/* this can't give carry */ \ - __x1 += __x2; /* but this indeed can */ \ - if (__x1 < __x2) /* did we get it? */ \ - __x3 += __ll_B; /* yes, add it in the proper pos. */ \ - \ + /* but this indeed can, and if so, add it in the proper pos: */ \ + add_ssaaaa(__x2, __x1, 0, __x1, 0, __x2); \ + __x3 += __x2 << (W_TYPE_SIZE / 2); \ (w1) = __x3 + __ll_highpart (__x1); \ (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\ } while (0) diff --git a/src/const-time.h b/src/const-time.h index 46eb187d..c2acbb73 100644 --- a/src/const-time.h +++ b/src/const-time.h @@ -82,6 +82,14 @@ unsigned int _gcry_ct_not_memequal (const void *b1, const void *b2, size_t len); any structure. */ unsigned int _gcry_ct_memequal (const void *b1, const void *b2, size_t len); +/* Prevent compiler from assuming value of variable and from making + non-constant time optimizations. */ +#ifdef HAVE_GCC_ASM_VOLATILE_MEMORY +# define CT_DEOPTIMIZE_VAR(var) asm volatile ("\n" : "+r" (var) :: "memory") +#else +# define CT_DEOPTIMIZE_VAR(var) (void)((var) += _gcry_ct_vzero) +#endif + /* * Return all bits set if A is 1 and return 0 otherwise. */ -- 2.45.2 From harmen at stoppels.ch Wed Feb 5 09:52:02 2025 From: harmen at stoppels.ch (Harmen Stoppels) Date: Wed, 05 Feb 2025 09:52:02 +0100 Subject: [PATCH] Simplify flag munging for rndjent.c Message-ID: * random/Makefile.am (o_flag_munging): append -O0 Replace `echo ... | sed` idiom with simply appending -O0. This overrides previous optimization flags. Hopefully that ends the series of patches to these lines. --- random/Makefile.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/random/Makefile.am b/random/Makefile.am index 41041e8a..b6487192 100644 --- a/random/Makefile.am +++ b/random/Makefile.am @@ -55,9 +55,9 @@ jitterentropy-base.c jitterentropy.h jitterentropy-base-user.h # The rndjent module needs to be compiled without optimization. */ if ENABLE_O_FLAG_MUNGING -o_flag_munging = sed -e 's/[[:blank:]]-O\([1-9sgz][1-9sgz]*\)/ -O0 /g' -e 's/[[:blank:]]-Ofast/ -O0 /g' +o_flag_munging = -O0 else -o_flag_munging = cat +o_flag_munging = endif rndjent.o: $(srcdir)/rndjent.c jitterentropy-base-user.h \ @@ -67,7 +67,7 @@ rndjent.o: $(srcdir)/rndjent.c jitterentropy-base-user.h \ $(srcdir)/jitterentropy-sha3.c $(srcdir)/jitterentropy-sha3.h \ $(srcdir)/jitterentropy-timer.c $(srcdir)/jitterentropy-timer.h \ $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h - `echo $(COMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) ` + $(COMPILE) $(o_flag_munging) -c $(srcdir)/rndjent.c rndjent.lo: $(srcdir)/rndjent.c jitterentropy-base-user.h \ $(srcdir)/jitterentropy-gcd.c $(srcdir)/jitterentropy-gcd.h \ @@ -76,4 +76,4 @@ rndjent.lo: $(srcdir)/rndjent.c jitterentropy-base-user.h \ $(srcdir)/jitterentropy-sha3.c $(srcdir)/jitterentropy-sha3.h \ $(srcdir)/jitterentropy-timer.c $(srcdir)/jitterentropy-timer.h \ $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h - `echo $(LTCOMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) ` + $(LTCOMPILE) $(o_flag_munging) -c $(srcdir)/rndjent.c -- 2.43.0 From gniibe at fsij.org Thu Feb 6 08:22:15 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 06 Feb 2025 16:22:15 +0900 Subject: [PATCH] Simplify flag munging for rndjent.c In-Reply-To: References: Message-ID: <87jza3y1ug.fsf@akagi.fsij.org> Hello, "Harmen Stoppels" wrote: > * random/Makefile.am (o_flag_munging): append -O0 > > Replace `echo ... | sed` idiom with simply appending -O0. This overrides > previous optimization flags. Hopefully that ends the series of patches > to these lines. Yes, GCC and Clang have this behavior; In GCC manual, it says: If you use multiple '-O' options, with or without level numbers, the last such option is the one that is effective. However, not all compilers have this behavior. So, please don't change. Well, I would understand your intention to prefer simpler things. Thank you for your attempt. -- From harmen at stoppels.ch Thu Feb 6 10:51:33 2025 From: harmen at stoppels.ch (Harmen Stoppels) Date: Thu, 06 Feb 2025 10:51:33 +0100 Subject: [PATCH] Simplify flag munging for rndjent.c In-Reply-To: <87jza3y1ug.fsf@akagi.fsij.org> References: <87jza3y1ug.fsf@akagi.fsij.org> Message-ID: <0ba70378-ab66-49cd-9055-ea73e02dce3c@app.fastmail.com> Any examples of compilers that do not do that? On Thu, Feb 6, 2025, at 8:22 AM, NIIBE Yutaka wrote: > Hello, > > "Harmen Stoppels" wrote: >> * random/Makefile.am (o_flag_munging): append -O0 >> >> Replace `echo ... | sed` idiom with simply appending -O0. This overrides >> previous optimization flags. Hopefully that ends the series of patches >> to these lines. > > Yes, GCC and Clang have this behavior; In GCC manual, it says: > > If you use multiple '-O' options, with or without level numbers, > the last such option is the one that is effective. > > However, not all compilers have this behavior. So, please don't change. > > Well, I would understand your intention to prefer simpler things. Thank > you for your attempt. > -- From gniibe at fsij.org Fri Feb 7 01:08:30 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 07 Feb 2025 09:08:30 +0900 Subject: [PATCH] Simplify flag munging for rndjent.c In-Reply-To: <0ba70378-ab66-49cd-9055-ea73e02dce3c@app.fastmail.com> References: <87jza3y1ug.fsf@akagi.fsij.org> <0ba70378-ab66-49cd-9055-ea73e02dce3c@app.fastmail.com> Message-ID: <87v7tm4nwh.fsf@akagi.fsij.org> "Harmen Stoppels" writes: > Any examples of compilers that do not do that? Since we occasionally got reports from IBM, this time, I tested on AIX, specifically, on the cfarm111 machine [0]. For the IBM XL C compiler on that machine, appending -O0 doesn't work as you intended. While it allows multiple -O[number] options, its decision seems to be most higher optimization level among multiple options. [0] https://portal.cfarm.net/machines/list/ -- From gniibe at fsij.org Fri Feb 7 06:28:43 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 07 Feb 2025 14:28:43 +0900 Subject: [PATCH] MPI helper of comparison, Least Leak Intended (was: [PATCH] MPI helper of multiplication, Least Leak Intended) In-Reply-To: <87seovj2cn.fsf@akagi.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> Message-ID: <87plju492s.fsf@akagi.fsij.org> Hello, This is not related to modular exponentiation, but another function for constant-time; MPI comparison by a helper function. I think that this implementation could be improved. Anyhow, let us start having the function for comparison. diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h index ffe8140a..0840d1fd 100644 --- a/mpi/mpi-internal.h +++ b/mpi/mpi-internal.h @@ -304,6 +304,7 @@ void _gcry_mpih_abs_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_ptr_t _gcry_mpih_mod_lli (mpi_ptr_t vp, mpi_size_t vsize, mpi_ptr_t up, mpi_size_t usize); int _gcry_mpih_cmp_ui (mpi_ptr_t up, mpi_size_t usize, unsigned long v); +int _gcry_mpih_cmp_lli (mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size); /* Define stuff for longlong.h. */ diff --git a/mpi/mpih-const-time.c b/mpi/mpih-const-time.c index e684b956..4549ebca 100644 --- a/mpi/mpih-const-time.c +++ b/mpi/mpih-const-time.c @@ -239,3 +239,25 @@ _gcry_mpih_cmp_ui (mpi_ptr_t up, mpi_size_t usize, unsigned long v) } return 1; } + +/* Do same calculation as _gcry_mpih_cmp does, but Least Leak Intended. + * Return 1 if U > V, 0 if they are equal, and -1 if U < V. */ +int +_gcry_mpih_cmp_lli (mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) +{ + mpi_size_t i; + mpi_limb_t gt, lt; + mpi_limb_t result = 0; + + for (i = 0; i < size ; i++) + { + gt = mpih_ct_limb_greater_than (up[i], vp[i]); + lt = mpih_ct_limb_less_than (up[i], vp[i]); + /* result = gt ? 1 : result; */ + result = (result & (- mpih_limb_is_zero (gt))) | gt; + /* result = lt ? -1 : result; */ + result = (result & (- mpih_limb_is_zero (lt))) | -lt; + } + + return result; +} -- From gniibe at fsij.org Sat Feb 8 03:05:08 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Sat, 08 Feb 2025 11:05:08 +0900 Subject: [PATCH] MPI helper of comparison, Least Leak Intended (was: [PATCH] MPI helper of multiplication, Least Leak Intended) In-Reply-To: <87plju492s.fsf@akagi.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <87plju492s.fsf@akagi.fsij.org> Message-ID: <87frkpmbsb.fsf@haruna.fsij.org> NIIBE Yutaka wrote: > I think that this implementation could be improved. I should use ct_limb_gen_inv_mask function instead of directly use unary minus operator. -- -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-mpi-Add-_gcry_mpih_cmp_lli-for-Least-Leak-Intended-c.patch Type: text/x-diff Size: 1950 bytes Desc: not available URL: From jcb62281 at gmail.com Sat Feb 8 02:49:17 2025 From: jcb62281 at gmail.com (Jacob Bachmeyer) Date: Fri, 7 Feb 2025 19:49:17 -0600 Subject: [PATCH] MPI helper of comparison, Least Leak Intended In-Reply-To: <87plju492s.fsf@akagi.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <87plju492s.fsf@akagi.fsij.org> Message-ID: On 2/6/25 23:28, NIIBE Yutaka via Gcrypt-devel wrote: > Hello, > > This is not related to modular exponentiation, but another function for > constant-time; MPI comparison by a helper function. > > I think that this implementation could be improved. Anyhow, let us > start having the function for comparison. While I am not entirely familiar with the details of the Gcryipt MPI implementation, I am unsure of the equivalence some of the comments imply.? Details inline below. > diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h > index ffe8140a..0840d1fd 100644 > [...] > diff --git a/mpi/mpih-const-time.c b/mpi/mpih-const-time.c > index e684b956..4549ebca 100644 > --- a/mpi/mpih-const-time.c > +++ b/mpi/mpih-const-time.c > @@ -239,3 +239,25 @@ _gcry_mpih_cmp_ui (mpi_ptr_t up, mpi_size_t usize, unsigned long v) > } > return 1; > } > + > +/* Do same calculation as _gcry_mpih_cmp does, but Least Leak Intended. > + * Return 1 if U > V, 0 if they are equal, and -1 if U < V. */ > +int > +_gcry_mpih_cmp_lli (mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) > +{ > + mpi_size_t i; > + mpi_limb_t gt, lt; > + mpi_limb_t result = 0; If you can initialize an mpi_limb_t to literal zero, then I know that mpi_limb_t is an integer type. > + > + for (i = 0; i < size ; i++) > + { > + gt = mpih_ct_limb_greater_than (up[i], vp[i]); > + lt = mpih_ct_limb_less_than (up[i], vp[i]); To check my understanding:? at most one of GT, LT can be non-zero; both are zero if UP[I]==VP[I].? I assume that the comparisons are done using function calls because "<" and ">" are not guaranteed to be constant-time? > + /* result = gt ? 1 : result; */ > + result = (result & (- mpih_limb_is_zero (gt))) | gt; > + /* result = lt ? -1 : result; */ > + result = (result & (- mpih_limb_is_zero (lt))) | -lt; Why are these using mpih_limb_is_zero when mpi_limb_t is an integer type? Assuming that mpih_liimb_is zero returns 1 if its argument is zero and 0 otherwise, in constant time, and we work from least-significant to most-significant, such that the last non-equal result determines the overall result, should these two lines instead be: result = (result & (- mpih_limb_is_zero (lt))) | gt; result = (result & (- mpih_limb_is_zero (gt))) | -lt; Since at most one of the flags can be set, each result line should pass the old value iff the /other/ flag is clear/zero. > + } > + > + return result; > +} > Overall comments and questions: Could this be made more efficient by defining an mpih_ct_limb_cmp function and then only needing to reduce it in constant time? Then we could work from the least-significant to most-significant limb and only need to find a constant-time evaluation of ({previous, this}) {X, -1} -> -1, {X, 1} -> 1, {X, 0} -> X. There might be a potential power-usage leak between setting 1 and -1 (the population counts radically differ); could we instead use 1 and 2 (adjacent bits, each one-hot) as the running flag values or even as the result codes?? (Maybe 1, 2, and 4 for one-hot encodings of less, equal, greater?) -- Jacob -------------- next part -------------- An HTML attachment was scrubbed... URL: From jcb62281 at gmail.com Sat Feb 8 23:50:42 2025 From: jcb62281 at gmail.com (Jacob Bachmeyer) Date: Sat, 8 Feb 2025 16:50:42 -0600 Subject: [PATCH] MPI helper of comparison, Least Leak Intended In-Reply-To: <87frkpmbsb.fsf@haruna.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <87plju492s.fsf@akagi.fsij.org> <87frkpmbsb.fsf@haruna.fsij.org> Message-ID: <89b5ea2f-03b5-43cb-ad85-645ccdb42c60@gmail.com> On 2/7/25 20:05, NIIBE Yutaka via Gcrypt-devel wrote: > NIIBE Yutaka wrote: >> I think that this implementation could be improved. > I should use ct_limb_gen_inv_mask function instead of directly use unary > minus operator. Could it make more sense to write: result &= ct_limb_gen_inv_mask (gt) & ct_limb_gen_inv_mask (lt); result |= gt | -lt; Assuming that ct_limb_gen_inv_mask returns all-bits-set if its argument is zero and all-bits-clear otherwise, the first line clears result if a previous value is to be overwritten and the second sets the new value. I also still suggest considering an alternate encoding for the comparison result.? The Hamming distance between 0 and 1 is 1, but the Hamming distance between 0 and -1 is the maximum on a 2's complement machine, which means that any information leakage on the power rail will be at its strongest when the comparison result is "less than". A one-hot encoding would have a constant Hamming distance (of 2) between any pair of valid values. I remember reading a paper some years ago by an academic research group that was able to recover private keys by observing noise on a laptop's ground (a USB port shield connection, if I recall correctly). -- Jacob -------------- next part -------------- An HTML attachment was scrubbed... URL: From jussi.kivilinna at iki.fi Sun Feb 9 15:06:22 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 9 Feb 2025 16:06:22 +0200 Subject: [PATCH] MPI helper of comparison, Least Leak Intended In-Reply-To: <89b5ea2f-03b5-43cb-ad85-645ccdb42c60@gmail.com> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <87plju492s.fsf@akagi.fsij.org> <87frkpmbsb.fsf@haruna.fsij.org> <89b5ea2f-03b5-43cb-ad85-645ccdb42c60@gmail.com> Message-ID: Hello, On 9.2.2025 0.50, Jacob Bachmeyer via Gcrypt-devel wrote: > On 2/7/25 20:05, NIIBE Yutaka via Gcrypt-devel wrote: >> NIIBE Yutaka wrote: >>> I think that this implementation could be improved. >> I should use ct_limb_gen_inv_mask function instead of directly use unary >> minus operator. > > Could it make more sense to write: > > result &= ct_limb_gen_inv_mask (gt) & ct_limb_gen_inv_mask (lt); > result |= gt | -lt; > > Assuming that ct_limb_gen_inv_mask returns all-bits-set if its argument is zero and all-bits-clear otherwise, the first line clears result if a previous value is to be overwritten and the second sets the new value. > > I also still suggest considering an alternate encoding for the comparison result.? The Hamming distance between 0 and 1 is 1, but the Hamming distance between 0 and -1 is the maximum on a 2's complement machine, which means that any information leakage on the power rail will be at its strongest when the comparison result is "less than". I'd move final result generation outside from the loop and instead generate separate result_lt and result_gt values in loop. These would then be combined at the end of function to form final result code. That should mostly mitigate the 0/1/-1 hamming distance EM leakage from inside the loop. int _gcry_mpih_cmp_lli (mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) { mpi_size_t i; mpi_limb_t res_gt = 0; mpi_limb_t res_lt = 0; for (i = 0; i < size ; i++) { mpi_limb_t gt, lt, eq, neq; gt = mpih_ct_limb_greater_than (up[i], vp[i]); lt = mpih_ct_limb_less_than (up[i], vp[i]); neq = ct_limb_gen_mask(gt | lt); eq = ct_limb_gen_inv_mask(gt | lt); res_gt = (eq & res_gt) | (neq & gt); res_lt = (eq & res_lt) | (neq & lt); } return (int)(res_gt - res_lt); /* return 0 if U==V, 1 if U>V, -1 if U > A one-hot encoding would have a constant Hamming distance (of 2) between any pair of valid values. If returned value (0 vs 1 vs -1) could cause EM leakage, last line of function could be changed to something like: return (int)(res_gt | (res_lt << 1)); /* return 0 if U==V, 1 if U>V, 2 if UV, INT_MIN if U References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <87plju492s.fsf@akagi.fsij.org> <87frkpmbsb.fsf@haruna.fsij.org> <89b5ea2f-03b5-43cb-ad85-645ccdb42c60@gmail.com> Message-ID: On 2/9/25 08:06, Jussi Kivilinna wrote: > Hello, > > On 9.2.2025 0.50, Jacob Bachmeyer via Gcrypt-devel wrote: >> On 2/7/25 20:05, NIIBE Yutaka via Gcrypt-devel wrote: >>> NIIBE Yutaka wrote: >>>> I think that this implementation could be improved. >>> I should use ct_limb_gen_inv_mask function instead of directly use >>> unary >>> minus operator. >> >> Could it make more sense to write: >> >> result &= ct_limb_gen_inv_mask (gt) & ct_limb_gen_inv_mask (lt); >> result |= gt | -lt; >> >> Assuming that ct_limb_gen_inv_mask returns all-bits-set if its >> argument is zero and all-bits-clear otherwise, the first line clears >> result if a previous value is to be overwritten and the second sets >> the new value. >> >> I also still suggest considering an alternate encoding for the >> comparison result.? The Hamming distance between 0 and 1 is 1, but >> the Hamming distance between 0 and -1 is the maximum on a 2's >> complement machine, which means that any information leakage on the >> power rail will be at its strongest when the comparison result is >> "less than". > > I'd move final result generation outside from the loop and instead > generate separate result_lt and result_gt values in loop. These would > then be combined at the end of function to form final result code. > That should mostly mitigate the 0/1/-1 hamming distance EM leakage > from inside the loop. > > [...] I had not thought of that.? Thank you. >> >> A one-hot encoding would have a constant Hamming distance (of 2) >> between any pair of valid values. > > If returned value (0 vs 1 vs -1) could cause EM leakage, last line of > function could be changed to something like: > > ? return (int)(res_gt | (res_lt << 1)); /* return 0 if U==V, 1 if U>V, > 2 if U > Or if having sign-bit set is important but we want to avoid "set all > bits to ones" case, then only set sign-bit for "U > ? return (int)(res_gt | (res_lt << (sizeof(int) * CHAR_BIT - 1))); /* > return 0 if U==V, 1 if U>V, INT_MIN if U References: Message-ID: Hi, Previous patch unintentionally differentiated GCRY_CIPHER_MODE_CMAC in FIPS mode. Attached is a patch to fix this. Also, following previous comments on this thread, implementation of _gcry_cipher_mode_fips_compliance was factored out to support enum gcry_cipher_modes and enum gcry_cipher_internal_modes. Best, M?lling -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-cipher-Don-t-differentiate-GCRY_CIPHER_MODE_CMAC-in-FIPS-mode.patch Type: text/x-patch Size: 2049 bytes Desc: not available URL: From lucas.mulling at suse.com Mon Feb 3 19:56:35 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Mon, 03 Feb 2025 15:56:35 -0300 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI Message-ID: Hi, Consider: NIST's deprecation of SHA1, effective 2030-12-31. Patch series to make SHA1 non-FIPS compliant and differentiate in the SLI, by means of GCRY_FIPS_FLAG_REJECT_MD_SHA1. Best, M?lling -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-md-Make-SHA1-non-FIPS-and-differentiate-in-the-SLI.patch Type: text/x-patch Size: 12209 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0002-cipher-Differentiate-SHA1-with-GCRY_FIPS_FLAG_REJECT_MD_SHA1.patch Type: text/x-patch Size: 7237 bytes Desc: not available URL: From hkario at redhat.com Mon Feb 10 16:28:48 2025 From: hkario at redhat.com (Alicja Kario) Date: Mon, 10 Feb 2025 16:28:48 +0100 Subject: [PATCH] MPI helper of comparison, Least Leak Intended In-Reply-To: References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <87plju492s.fsf@akagi.fsij.org> <87frkpmbsb.fsf@haruna.fsij.org> <89b5ea2f-03b5-43cb-ad85-645ccdb42c60@gmail.com> Message-ID: <52e75f0d-d6ef-4074-b69f-1cb2bc27de1d@redhat.com> On Monday, 10 February 2025 05:02:12 CET, Jacob Bachmeyer via Gcrypt-devel wrote: > On 2/9/25 08:06, Jussi Kivilinna wrote: >> Hello, >> >> On 9.2.2025 0.50, Jacob Bachmeyer via Gcrypt-devel wrote: ... > > I had not thought of that. Thank you. > >>> ... >> If returned value (0 vs 1 vs -1) could cause EM leakage, last >> line of function could be changed to something like: >> >> return (int)(res_gt | (res_lt << 1)); /* return 0 if U==V, 1 >> if U>V, 2 if U> >> Or if having sign-bit set is important but we want to avoid >> "set all bits to ones" case, then only set sign-bit for "U> >> return (int)(res_gt | (res_lt << (sizeof(int) * CHAR_BIT - >> 1))); /* return 0 if U==V, 1 if U>V, INT_MIN if U > This still leaves a small difference between "equal" (Hamming > weight of zero) and "not equal" (both with Hamming weight of > one). I was originally thinking of using 1, 2, and 4 as result > codes to avoid that difference. > > However, using 0 vs 1 vs INT_MIN certainly greatly reduces the > potential leak. Would it be expected to weaken the signal > enough for it to be lost in the other noise in a practical > system? > > For example, the Hamming weights of the MPI limbs are > definitely variable, and I am unsure if there is anything > software can reasonably do to mitigate that. Storing both true > and complement might help, but would be a different in-memory > representation and computing with both might even make a > stronger signal. > > I think using 0/1/INT_MIN as results is probably the best we > can do if we want to keep to the C convention of using > comparison to zero as a proxy for the result of a complex > comparison. There are still several 0 vs 1 values used in the > loop, but changing that would likely cascade throughout the MPI > implementation. Proper CPUs (stuff that's running in servers or desktops) do not have timing differences on operands of bitwise instructions. The only possibly problematic one is integer division. This kind of Hamming weight leakage is important for EM or power leakage on super small embedded CPUs. And that kind of leakage is outside the threat model of libgcrypt: https://www.gnupg.org/documentation/security.html > Those hardware related threats are out of scope in Libgcrypt's threat model. It is up to users not to offer any access to those side-channels. It's necessary to not use < or > operands in C code because of the jumps the compiler creates, not because the actual hardware instruction takes different amount of time depending on operands. -- Regards, Alicja (nee Hubert) Kario Principal Quality Engineer, RHEL Crypto team Web: www.cz.redhat.com Red Hat Czech s.r.o., Purky?ova 115, 612 00, Brno, Czech Republic From gniibe at fsij.org Tue Feb 11 02:33:52 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 11 Feb 2025 10:33:52 +0900 Subject: [PATCH 2/3] mpih-const-time: avoid branches in _gcry_mpih_cmp_ui In-Reply-To: <20250203192209.3072952-2-jussi.kivilinna@iki.fi> References: <20250203192209.3072952-1-jussi.kivilinna@iki.fi> <20250203192209.3072952-2-jussi.kivilinna@iki.fi> Message-ID: <87tt91nu2n.fsf@haruna.fsij.org> Hello, Jussi, Jussi Kivilinna wrote: > * mpi/mpih-const-time.c (_gcry_mpih_cmp_ui): Avoid conditional > branches for return value selection. Thank you for your work. This is good for constant-time property. Another one: [PATCH 3/3] mpi/longlong: prevent optimization of carry instructions to branches (inbox lists lists/gcrypt-devel) is also good. Please apply and push your changes of [PATCH 2/3] and [PATCH 3/3]. For the fix of: [PATCH 1/3] t-fips-service-ind: fix broken fail print (inbox lists lists/gcrypt-devel) This fix is also included by Lucas Mulling's post of 2025-01-28: Message-ID: I think that it's better applying his one (when Werner agrees). -- From gniibe at fsij.org Wed Feb 12 01:21:15 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 12 Feb 2025 09:21:15 +0900 Subject: [PATCH] MPI helper of comparison, Least Leak Intended In-Reply-To: References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <87plju492s.fsf@akagi.fsij.org> <87frkpmbsb.fsf@haruna.fsij.org> <89b5ea2f-03b5-43cb-ad85-645ccdb42c60@gmail.com> Message-ID: <87frkk2etg.fsf@haruna.fsij.org> Hello, Jussi, Thank you for looking into the MPI helper of comparison. Thanks a lot to Jacob Bachmeyer, for joining discussion and give us insights. Thank you to Alicja Kario, too. Jussi Kivilinna wrote: > int > _gcry_mpih_cmp_lli (mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) > { > mpi_size_t i; > mpi_limb_t res_gt = 0; > mpi_limb_t res_lt = 0; > > for (i = 0; i < size ; i++) > { > mpi_limb_t gt, lt, eq, neq; > gt = mpih_ct_limb_greater_than (up[i], vp[i]); > lt = mpih_ct_limb_less_than (up[i], vp[i]); > neq = ct_limb_gen_mask(gt | lt); > eq = ct_limb_gen_inv_mask(gt | lt); > res_gt = (eq & res_gt) | (neq & gt); > res_lt = (eq & res_lt) | (neq & lt); > } > > return (int)(res_gt - res_lt); /* return 0 if U==V, 1 if U>V, -1 if U } Please apply and push this version, because it's the way the function name suggests (returning -1, 0, 1). If we will see any problem (about possible EM leakage or whatever), then let us consider again in future. > If returned value (0 vs 1 vs -1) could cause EM leakage, last line of function could be changed to something like: > > return (int)(res_gt | (res_lt << 1)); /* return 0 if U==V, 1 if U>V, 2 if U > Or if having sign-bit set is important but we want to avoid "set all bits to ones" case, then only set sign-bit for "U > return (int)(res_gt | (res_lt << (sizeof(int) * CHAR_BIT - 1))); /* return 0 if U==V, 1 if U>V, INT_MIN if U References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <87plju492s.fsf@akagi.fsij.org> <87frkpmbsb.fsf@haruna.fsij.org> <89b5ea2f-03b5-43cb-ad85-645ccdb42c60@gmail.com> <87frkk2etg.fsf@haruna.fsij.org> Message-ID: <87cyfn3cnv.fsf@haruna.fsij.org> Sorry, this phrase came from my confusion. Please ignore this phrase. NIIBE Yutaka wrote: > The current use of _gcry_mpih_cmp_ui is only at one place. That is, > catching a wrong use case (where no inverse exists) in the function > mpih_invm_odd (libgcrypt/mpi/mpi-inv.c). So, one of these changes would > be possible (in future, if needed). But in such a case, I'd prefer > change of the function name (not cmp_ui, which suggests -1, 0, 1) so > that keeping least surprise. The topic in this thread is for _gcry_mpih_cmp_lli. -- From wk at gnupg.org Wed Feb 12 09:25:39 2025 From: wk at gnupg.org (Werner Koch) Date: Wed, 12 Feb 2025 09:25:39 +0100 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: (Lucas Mulling via Gcrypt-devel's message of "Mon, 03 Feb 2025 15:56:35 -0300") References: Message-ID: <8734gjfu2k.fsf@jacob.g10code.de> Hi! On Mon, 3 Feb 2025 15:56, Lucas Mulling said: > Consider: NIST's deprecation of SHA1, effective 2030-12-31. That are 5.5 years in the future. Not a good idea to do it now. Shalom-Salam, 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: 247 bytes Desc: not available URL: From wk at gnupg.org Wed Feb 12 09:53:29 2025 From: wk at gnupg.org (Werner Koch) Date: Wed, 12 Feb 2025 09:53:29 +0100 Subject: [PATCH] cipher: Check and mark non-compliant cipher modes in the SLI In-Reply-To: (Lucas Mulling via Gcrypt-devel's message of "Mon, 03 Feb 2025 13:50:17 -0300") References: Message-ID: <87y0ybee7q.fsf@jacob.g10code.de> Hi! On Mon, 3 Feb 2025 13:50, Lucas Mulling said: > Previous patch unintentionally differentiated GCRY_CIPHER_MODE_CMAC in > FIPS mode. Attached is a patch to fix this. Also, following previous Thanks. I extended the patch to actually allow to make use of -Wswitch and changed the name of the helpers because they have static scope. 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: 247 bytes Desc: not available URL: From cllang at redhat.com Wed Feb 12 13:50:43 2025 From: cllang at redhat.com (Clemens Lang) Date: Wed, 12 Feb 2025 13:50:43 +0100 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: <8734gjfu2k.fsf@jacob.g10code.de> References: <8734gjfu2k.fsf@jacob.g10code.de> Message-ID: Hi Werner, > On 12. Feb 2025, at 09:25, Werner Koch via Gcrypt-devel wrote: > > On Mon, 3 Feb 2025 15:56, Lucas Mulling said: > >> Consider: NIST's deprecation of SHA1, effective 2030-12-31. > > That are 5.5 years in the future. Not a good idea to do it now. This matters because FIPS validations are valid for five years, but will have their lifetime limited to NIST?s SHA1 sunset date if they allow SHA1. If you do a FIPS validation now, you?ll likely get a certificate in ~2 years, which then won?t be valid for 5, but only 3, because the build included support for SHA1. -- Clemens Lang RHEL Crypto Team Red Hat From lucas.mulling at suse.com Wed Feb 12 19:08:53 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Wed, 12 Feb 2025 15:08:53 -0300 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: References: <8734gjfu2k.fsf@jacob.g10code.de> Message-ID: On Wed Feb 12, 2025 at 9:50 AM -03, Clemens Lang wrote: > Hi Werner, > >> On 12. Feb 2025, at 09:25, Werner Koch via Gcrypt-devel wrote: >> >> On Mon, 3 Feb 2025 15:56, Lucas Mulling said: >> >>> Consider: NIST's deprecation of SHA1, effective 2030-12-31. >> >> That are 5.5 years in the future. Not a good idea to do it now. > > This matters because FIPS validations are valid for five years, but will have their lifetime limited to NIST?s SHA1 sunset date if they allow SHA1. > > If you do a FIPS validation now, you?ll likely get a certificate in ~2 years, which then won?t be valid for 5, but only 3, because the build included support for SHA1. Yes, also note that operations with SHA1 are not blocked by default, and should work normally unless GCRY_FIPS_FLAG_REJECT_MD_SHA1 is explicitly set. From gniibe at fsij.org Thu Feb 13 07:20:46 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 13 Feb 2025 15:20:46 +0900 Subject: [PATCH 2/3] mpih-const-time: avoid branches in _gcry_mpih_cmp_ui In-Reply-To: <20250203192209.3072952-2-jussi.kivilinna@iki.fi> References: <20250203192209.3072952-1-jussi.kivilinna@iki.fi> <20250203192209.3072952-2-jussi.kivilinna@iki.fi> Message-ID: <87h64ygybl.fsf@haruna.fsij.org> Hello, again for _gcry_mpih_cmp_ui, Jussi Kivilinna wrote: > * mpi/mpih-const-time.c (_gcry_mpih_cmp_ui): Avoid conditional > branches for return value selection. After the commit of this, I realize that there is a thinko. When IS_ALL_ZERO (meaning all the limbs sans the least one are zero) is false, the function should return 1 (instead of 0). Something like this: diff --git a/mpi/mpih-const-time.c b/mpi/mpih-const-time.c index d8b66c46..a6314932 100644 --- a/mpi/mpih-const-time.c +++ b/mpi/mpih-const-time.c @@ -232,5 +232,5 @@ _gcry_mpih_cmp_ui (mpi_ptr_t up, mpi_size_t usize, unsigned long v) for (i = 1; i < usize; i++) is_all_zero &= ct_ulong_gen_mask(mpih_limb_is_zero (up[i])); - return cmp0 & (int)is_all_zero; + return (cmp0 & (int)is_all_zero) | (~is_all_zero & 1); } -- From wk at gnupg.org Thu Feb 13 17:42:23 2025 From: wk at gnupg.org (Werner Koch) Date: Thu, 13 Feb 2025 17:42:23 +0100 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: (Lucas Mulling's message of "Wed, 12 Feb 2025 15:08:53 -0300") References: <8734gjfu2k.fsf@jacob.g10code.de> Message-ID: <875xldeqz4.fsf@jacob.g10code.de> On Wed, 12 Feb 2025 15:08, Lucas Mulling said: > On Wed Feb 12, 2025 at 9:50 AM -03, Clemens Lang wrote: >> If you do a FIPS validation now, you?ll likely get a certificate in >> ~2 years, which then won?t be valid for 5, but only 3, because the >> build included support for SHA1. Makes some sense iff we are not allowed to extend the API. > Yes, also note that operations with SHA1 are not blocked by default, and > should work normally unless GCRY_FIPS_FLAG_REJECT_MD_SHA1 is explicitly set. Alright. Then let's add this too. 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: 247 bytes Desc: not available URL: From jussi.kivilinna at iki.fi Thu Feb 13 20:01:02 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 13 Feb 2025 21:01:02 +0200 Subject: [PATCH 2/3] mpih-const-time: avoid branches in _gcry_mpih_cmp_ui In-Reply-To: <87h64ygybl.fsf@haruna.fsij.org> References: <20250203192209.3072952-1-jussi.kivilinna@iki.fi> <20250203192209.3072952-2-jussi.kivilinna@iki.fi> <87h64ygybl.fsf@haruna.fsij.org> Message-ID: <64707d7e-179e-40c3-8a64-115e3777c334@iki.fi> Hello, On 13.2.2025 8.20, NIIBE Yutaka wrote: > Hello, again for _gcry_mpih_cmp_ui, > > Jussi Kivilinna wrote: >> * mpi/mpih-const-time.c (_gcry_mpih_cmp_ui): Avoid conditional >> branches for return value selection. > > After the commit of this, I realize that there is a thinko. > > When IS_ALL_ZERO (meaning all the limbs sans the least one are zero) > is false, the function should return 1 (instead of 0). Ah, that's right. Here's patch attach with new tests to catch this. I'll push this to master soon. -Jussi > > Something like this: > > diff --git a/mpi/mpih-const-time.c b/mpi/mpih-const-time.c > index d8b66c46..a6314932 100644 > --- a/mpi/mpih-const-time.c > +++ b/mpi/mpih-const-time.c > @@ -232,5 +232,5 @@ _gcry_mpih_cmp_ui (mpi_ptr_t up, mpi_size_t usize, unsigned long v) > for (i = 1; i < usize; i++) > is_all_zero &= ct_ulong_gen_mask(mpih_limb_is_zero (up[i])); > > - return cmp0 & (int)is_all_zero; > + return (cmp0 & (int)is_all_zero) | (~is_all_zero & 1); > } > -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-mpih-const-time-fix-return-value-for-_gcry_mpih_cmp_.patch Type: text/x-patch Size: 3793 bytes Desc: not available URL: From gniibe at fsij.org Fri Feb 14 01:13:22 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 14 Feb 2025 09:13:22 +0900 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: <875xldeqz4.fsf@jacob.g10code.de> References: <8734gjfu2k.fsf@jacob.g10code.de> <875xldeqz4.fsf@jacob.g10code.de> Message-ID: <87ikpdqt7h.fsf@haruna.fsij.org> Hello, I pushed the changes by Lucas Mulling as the commit of: 13a71215c255377863b0154ac602c86fe5450c49 If there are changes needed for the service indicator, please let us know. -- From gniibe at fsij.org Fri Feb 14 02:25:41 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 14 Feb 2025 10:25:41 +0900 Subject: [PATCH] MPI helper of addition one limb, Least Leak Intended References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> Message-ID: <877c5tqpuy.fsf@haruna.fsij.org> Hello, This change introduces a function _gcry_mpih_add_1_lli for one limb addition with least leak. diff --git a/mpi/mpi-inline.h b/mpi/mpi-inline.h index 090e8a94..6954affb 100644 --- a/mpi/mpi-inline.h +++ b/mpi/mpi-inline.h @@ -68,6 +68,28 @@ _gcry_mpih_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, } +/* Do same calculation as _gcry_mpih_add_1 does (under the condition + of RES_PTR == S1_PTR), Least Leak Intended. */ +static inline mpi_limb_t +_gcry_mpih_add_1_lli (mpi_ptr_t s1_ptr, mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t x; + mpi_limb_t cy; + + x = *s1_ptr; + s2_limb += x; + *s1_ptr++ = s2_limb; + cy = (s2_limb < x); + while ( --s1_size ) + { + x = *s1_ptr + cy; + *s1_ptr++ = x; + cy = mpih_limb_is_zero (x) & mpih_limb_is_not_zero (cy); + } + + return cy; +} + G10_MPI_INLINE_DECL mpi_limb_t _gcry_mpih_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, -- From jcb62281 at gmail.com Fri Feb 14 05:57:07 2025 From: jcb62281 at gmail.com (Jacob Bachmeyer) Date: Thu, 13 Feb 2025 22:57:07 -0600 Subject: [PATCH] MPI helper of addition one limb, Least Leak Intended In-Reply-To: <877c5tqpuy.fsf@haruna.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <877c5tqpuy.fsf@haruna.fsij.org> Message-ID: <38303496-0a57-481a-a897-9c185ebc407a@gmail.com> On 2/13/25 19:25, NIIBE Yutaka via Gcrypt-devel wrote: > Hello, > > This change introduces a function _gcry_mpih_add_1_lli for one limb > addition with least leak. > > diff --git a/mpi/mpi-inline.h b/mpi/mpi-inline.h > index 090e8a94..6954affb 100644 > --- a/mpi/mpi-inline.h > +++ b/mpi/mpi-inline.h > @@ -68,6 +68,28 @@ _gcry_mpih_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, > } > > > +/* Do same calculation as _gcry_mpih_add_1 does (under the condition > + of RES_PTR == S1_PTR), Least Leak Intended. */ > +static inline mpi_limb_t > +_gcry_mpih_add_1_lli (mpi_ptr_t s1_ptr, mpi_size_t s1_size, mpi_limb_t s2_limb) > +{ > + mpi_limb_t x; > + mpi_limb_t cy; > + > + x = *s1_ptr; > + s2_limb += x; > + *s1_ptr++ = s2_limb; > + cy = (s2_limb < x); > + while ( --s1_size ) > + { > + x = *s1_ptr + cy; > + *s1_ptr++ = x; > + cy = mpih_limb_is_zero (x) & mpih_limb_is_not_zero (cy); > + } > + > + return cy; > +} > + Looking at this, I can now deduce that MPI values are stored in little-endian order, "x" is a working register, and "cy" is a carry flag. If I read this correctly, the carry handling is depending on integer overflow wrapping around, which is not actually defined behavior in C, although most platforms do handle it that way.? Do we have an MPI_LIMB_MAX constant analogous to INT_MAX but for mpi_limb_t instead of int? Also, if I understand correctly from the previous discussion, "<" is to be avoided because compilers can use a branch to implement it.? Unfortunately, I am unsure if there is any way short of simulating an adder block to do this without using a relational operator and/or relying on undefined behavior. -- Jacob From gniibe at fsij.org Fri Feb 14 06:01:23 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 14 Feb 2025 14:01:23 +0900 Subject: [PATCH] MPI helper of table lookup, Least Leak Intended In-Reply-To: <87seovj2cn.fsf@akagi.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> Message-ID: <874j0xqfvg.fsf@haruna.fsij.org> Hello, This change introduces a function _gcry_mpih_table_lookup. The idea is accessing the whole table entries (so that cache timing won't possible) and select the value by ct_limb_select. Your suggestions/comments for the implementation and/or for the suitable name for the function are welcome. For the use case of the function, please have a look at gniibe/t7490 branch of libgcrypt: https://dev.gnupg.org/source/libgcrypt/browse/gniibe%252Ft7490/ diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h index ffe8140a..decaadd8 100644 --- a/mpi/mpi-internal.h +++ b/mpi/mpi-internal.h @@ -272,6 +275,7 @@ mpi_limb_t _gcry_mpih_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, DEFINE_CT_TYPE_GEN_MASK(limb, mpi_limb_t) DEFINE_CT_TYPE_GEN_INV_MASK(limb, mpi_limb_t) +DEFINE_CT_TYPE_SELECT_FUNC(limb, mpi_limb_t) static inline int mpih_limb_is_zero (mpi_limb_t a) @@ -301,6 +305,8 @@ void _gcry_mpih_swap_cond (mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t usize, unsigned long op_enable); void _gcry_mpih_abs_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned long op_enable); +void _gcry_mpih_table_lookup (mpi_ptr_t rp, const mpi_limb_t *table, + mpi_size_t n, mpi_size_t nents, mpi_size_t idx); mpi_ptr_t _gcry_mpih_mod_lli (mpi_ptr_t vp, mpi_size_t vsize, mpi_ptr_t up, mpi_size_t usize); int _gcry_mpih_cmp_ui (mpi_ptr_t up, mpi_size_t usize, unsigned long v); diff --git a/mpi/mpih-const-time.c b/mpi/mpih-const-time.c index 9c2cd6a9..78c66da5 100644 --- a/mpi/mpih-const-time.c +++ b/mpi/mpih-const-time.c @@ -1,5 +1,5 @@ /* mpih-const-time.c - Constant-time MPI helper functions - * Copyright (C) 2020 g10 Code GmbH + * Copyright (C) 2020, 2025 g10 Code GmbH * * This file is part of Libgcrypt. * @@ -183,6 +183,28 @@ _gcry_mpih_abs_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, } +/* + * Lookup an MPI value from TABLE at IDX, and put into RP. + * The size of the MPI value is N limbs. + * TABLE has NENTS entries. + */ +void +_gcry_mpih_table_lookup (mpi_ptr_t rp, const mpi_limb_t *table, + mpi_size_t n, mpi_size_t nents, mpi_size_t idx) +{ + mpi_size_t i, k; + const mpi_limb_t *tp = table; + + for (k = 0; k < nents; k++) + { + unsigned long idx_neq_k = ct_is_not_zero (idx ^ k); + for (i = 0; i < n; i++) + rp[i] = ct_limb_select (rp[i], tp[i], idx_neq_k); + tp += n; + } +} + + /* * Allocating memory for W, * compute W = V % U, then return W -- From jussi.kivilinna at iki.fi Fri Feb 14 06:41:23 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 14 Feb 2025 07:41:23 +0200 Subject: [PATCH] MPI helper of addition one limb, Least Leak Intended In-Reply-To: <38303496-0a57-481a-a897-9c185ebc407a@gmail.com> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <877c5tqpuy.fsf@haruna.fsij.org> <38303496-0a57-481a-a897-9c185ebc407a@gmail.com> Message-ID: On 14.2.2025 6.57, Jacob Bachmeyer via Gcrypt-devel wrote: > On 2/13/25 19:25, NIIBE Yutaka via Gcrypt-devel wrote: >> Hello, >> >> This change introduces a function _gcry_mpih_add_1_lli for one limb >> addition with least leak. >> >> diff --git a/mpi/mpi-inline.h b/mpi/mpi-inline.h >> index 090e8a94..6954affb 100644 >> --- a/mpi/mpi-inline.h >> +++ b/mpi/mpi-inline.h >> @@ -68,6 +68,28 @@ _gcry_mpih_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, >> ? } >> +/* Do same calculation as _gcry_mpih_add_1 does (under the condition >> +?? of RES_PTR == S1_PTR), Least Leak Intended.? */ >> +static inline mpi_limb_t >> +_gcry_mpih_add_1_lli (mpi_ptr_t s1_ptr, mpi_size_t s1_size, mpi_limb_t s2_limb) >> +{ >> +? mpi_limb_t x; >> +? mpi_limb_t cy; >> + >> +? x = *s1_ptr; >> +? s2_limb += x; >> +? *s1_ptr++ = s2_limb; >> +? cy = (s2_limb < x); >> +? while ( --s1_size ) >> +??? { >> +????? x = *s1_ptr + cy; >> +????? *s1_ptr++ = x; >> +????? cy = mpih_limb_is_zero (x) & mpih_limb_is_not_zero (cy); >> +??? } >> + >> +? return cy; >> +} >> + > > Looking at this, I can now deduce that MPI values are stored in little-endian order, "x" is a working register, and "cy" is a carry flag. > > If I read this correctly, the carry handling is depending on integer overflow wrapping around, which is not actually defined behavior in C, although most platforms do handle it that way.? Do we have an MPI_LIMB_MAX constant analogous to INT_MAX but for mpi_limb_t instead of int? > Limbs are unsigned integers and unsigned integer overflow is defined behavior. -Jussi From gniibe at fsij.org Fri Feb 14 07:00:11 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 14 Feb 2025 15:00:11 +0900 Subject: [PATCH] MPI helper of addition one limb, Least Leak Intended In-Reply-To: <38303496-0a57-481a-a897-9c185ebc407a@gmail.com> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <877c5tqpuy.fsf@haruna.fsij.org> <38303496-0a57-481a-a897-9c185ebc407a@gmail.com> Message-ID: <871pw1qd5g.fsf@haruna.fsij.org> Hello, Jacob Bachmeyer wrote: > Also, if I understand correctly from the previous discussion, "<" is to > be avoided because compilers can use a branch to implement it.? Than you. Good catch. It is the reason why we have mpih_ct_limb_less_than. Using mpih_ct_limb_less_than, it is like: ========================== /* Do same calculation as _gcry_mpih_add_1 does (under the condition of RES_PTR == S1_PTR), Least Leak Intended. */ static inline mpi_limb_t _gcry_mpih_add_1_lli (mpi_ptr_t s1_ptr, mpi_size_t s1_size, mpi_limb_t s2_limb) { mpi_limb_t x; mpi_limb_t cy; x = *s1_ptr; s2_limb += x; *s1_ptr++ = s2_limb; cy = mpih_ct_limb_less_than (s2_limb, x); while ( --s1_size ) { x = *s1_ptr + cy; *s1_ptr++ = x; cy = mpih_limb_is_zero (x) & mpih_limb_is_not_zero (cy); } return cy; } ========================== We will need to arrange header files to allow use of mpih_ct_limb_less_than, though. -- From jcb62281 at gmail.com Fri Feb 14 07:08:20 2025 From: jcb62281 at gmail.com (Jacob Bachmeyer) Date: Fri, 14 Feb 2025 00:08:20 -0600 Subject: [PATCH] MPI helper of addition one limb, Least Leak Intended In-Reply-To: References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <877c5tqpuy.fsf@haruna.fsij.org> <38303496-0a57-481a-a897-9c185ebc407a@gmail.com> Message-ID: On 2/13/25 23:41, Jussi Kivilinna wrote: > On 14.2.2025 6.57, Jacob Bachmeyer via Gcrypt-devel wrote: >> [...] >> >> If I read this correctly, the carry handling is depending on integer >> overflow wrapping around, which is not actually defined behavior in >> C, although most platforms do handle it that way. Do we have an >> MPI_LIMB_MAX constant analogous to INT_MAX but for mpi_limb_t instead >> of int? >> > > Limbs are unsigned integers and unsigned integer overflow is defined > behavior. Aha... I had forgotten that unsigned integers do wrap.? Thank you. -- Jacob From jcb62281 at gmail.com Fri Feb 14 07:08:26 2025 From: jcb62281 at gmail.com (Jacob Bachmeyer) Date: Fri, 14 Feb 2025 00:08:26 -0600 Subject: [PATCH] MPI helper of addition one limb, Least Leak Intended In-Reply-To: <871pw1qd5g.fsf@haruna.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <877c5tqpuy.fsf@haruna.fsij.org> <38303496-0a57-481a-a897-9c185ebc407a@gmail.com> <871pw1qd5g.fsf@haruna.fsij.org> Message-ID: <076b6a5a-c93a-4bc8-969c-e556e8b1763f@gmail.com> On 2/14/25 00:00, NIIBE Yutaka wrote: > Hello, > > Jacob Bachmeyer wrote: >> Also, if I understand correctly from the previous discussion, "<" is to >> be avoided because compilers can use a branch to implement it. > Than you. Good catch. It is the reason why we have > mpih_ct_limb_less_than. You are welcome.? Glad to have been of help. -- Jacob From jcb62281 at gmail.com Fri Feb 14 07:27:45 2025 From: jcb62281 at gmail.com (Jacob Bachmeyer) Date: Fri, 14 Feb 2025 00:27:45 -0600 Subject: [PATCH] MPI helper of table lookup, Least Leak Intended In-Reply-To: <874j0xqfvg.fsf@haruna.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <874j0xqfvg.fsf@haruna.fsij.org> Message-ID: On 2/13/25 23:01, NIIBE Yutaka via Gcrypt-devel wrote: > Hello, > > This change introduces a function _gcry_mpih_table_lookup. The idea is > accessing the whole table entries (so that cache timing won't possible) > and select the value by ct_limb_select. > > Your suggestions/comments for the implementation and/or for the suitable > name for the function are welcome. The obvious comment to me is that the function name should probably contain either "_ct" or "_lli" to denote that this is a slow function for leak minimization. There might also be architecture-specific instructions that can be used to retrieve a table row without polluting the data cache; allowing architecture-specific overrides here could make a very significant performance difference, as the basic implementation could easily flush the entire data cache if used on a large table. For the base case, reading the entire table is probably the best that you can do, but if you have a "load without temporal locality" instruction (I believe that there are such instructions in SSE, for example), you can avoid the problem, while accessing only a single table row.? (The memory bus is assumed to not be visible to an attacker.) Even if that instruction can only load to a vector unit, you can simply allocate a scratch row on the stack with the required alignment, store it there from the vector unit and copy it to the result buffer.? Of course the stack and result buffers would be in the data cache, so no leak there. In short, I suggest planning for future enhancement here, using either assembler or intrinsics.? This is an operation that, in portable C, is going to have nasty performance-hindering side effects but /might/ be less expensive on some architectures. -- Jacob From gniibe at fsij.org Fri Feb 14 08:44:13 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 14 Feb 2025 16:44:13 +0900 Subject: [PATCH] MPI helper modular exponentiation, Least Leak Intended References: <877c6b8pp8.fsf@akagi.fsij.org> Message-ID: <87tt8xdl82.fsf@haruna.fsij.org> Hello, again, NIIBE Yutaka wrote: > This month, I created the ticket for improvement of modular > exponentiation implementation with a branch named gniibe/t7490: > > https://dev.gnupg.org/T7490 > > It somehow works for me now. > > I'd like to merge the branch manually in steps. Here is the last and main part of the changes for the modular exponentiation implementation (it's by Montgomery exponentiation algorithm). I put the changes inline, so that people can easily reply and comment. FYI, the reference, Handbook of Applied Cryptography is available: https://cacr.uwaterloo.ca/hac/ diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h index ffe8140a..decaadd8 100644 --- a/mpi/mpi-internal.h +++ b/mpi/mpi-internal.h @@ -261,6 +261,9 @@ mpi_limb_t _gcry_mpih_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt); mpi_limb_t _gcry_mpih_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt); +/*-- mpih-pow.c --*/ +void _gcry_mpih_powm_lli (mpi_ptr_t rp, mpi_ptr_t bp, mpi_ptr_t mp, + mpi_size_t n, mpi_ptr_t ep, mpi_size_t en); /*-- mpih-const-time.c --*/ #define mpih_set_cond(w,u,s,o) _gcry_mpih_set_cond ((w),(u),(s),(o)) diff --git a/mpi/mpi-pow.c b/mpi/mpi-pow.c index defd675e..ef410a60 100644 --- a/mpi/mpi-pow.c +++ b/mpi/mpi-pow.c @@ -34,6 +34,21 @@ #include "longlong.h" +#ifndef USE_ALGORITHM_LLI_EXPONENTIATION +/* + * When you don't need least-leak implementation, please add compilation option + * -DUSE_ALGORITHM_LLI_EXPONENTIATION=0 + * + * For performance (by tests/benchmark rsa), it's comparable to leaky + * sliding window implementation on 64-bit architecture. On 32-bit + * architecture, it's slower with 3072-bit and 4096-bit. In future, + * it's good to have non-leaky Karatsuba multiplication, then, it's an + * option to use it. + * + */ +#define USE_ALGORITHM_LLI_EXPONENTIATION 1 +#endif + /* * When you need old implementation, please add compilation option * -DUSE_ALGORITHM_SIMPLE_EXPONENTIATION @@ -41,6 +56,16 @@ #define USE_ALGORITHM_SIMPLE_EXPONENTIATION 1 */ +const char * +_gcry_mpi_get_powm_config (void) +{ +#if USE_ALGORITHM_LLI_EXPONENTIATION + return "fixed-window"; +#else + return "sliding-window"; +#endif +} + #if defined(USE_ALGORITHM_SIMPLE_EXPONENTIATION) /**************** * RES = BASE ^ EXPO mod MOD @@ -541,6 +566,33 @@ _gcry_mpi_powm (gcry_mpi_t res, rp = res->d; } +#if USE_ALGORITHM_LLI_EXPONENTIATION + if ((esec || bsec || msec) && (mod->d[0] & 1)) + { + mpi_ptr_t bp1 = NULL; + + if (bsize < msize) + { + bp1 = mpi_alloc_limb_space (msize, 1); + MPN_ZERO (bp1, msize); + MPN_COPY (bp1, bp, bsize); + } + + _gcry_mpih_powm_lli (rp, bp1?bp1:bp, mod->d, msize, ep, esize); + if (bp1) + _gcry_mpi_free_limb_space (bp1, msize); + + rsign = 0; + negative_result = (ep[0] & 1) && bsign; + if (negative_result) + rsign = msign; + + res->nlimbs = msize; + res->sign = rsign; + goto leave; + } +#endif + /* Main processing. */ { mpi_size_t i, j, k; diff --git a/mpi/mpih-pow.c b/mpi/mpih-pow.c new file mode 100644 index 00000000..ad7d1e8d --- /dev/null +++ b/mpi/mpih-pow.c @@ -0,0 +1,283 @@ +/* mpih-pow.c - MPI helper functions + * Copyright (C) 2025 g10 Code GmbH + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + * SPDX-License-Identifier: LGPL-2.1-or-later + * + */ + +#include +#include +#include +#include "mpi-internal.h" +#include "longlong.h" + +#if BITS_PER_MPI_LIMB <= 32 +#define MAX_SCRATCH_SPACE 256*2 +#define MAX_WINDOW 8 +#else +#define MAX_SCRATCH_SPACE 256 +#define MAX_WINDOW 4 +#endif + +/* + * Compute -N^(-1) mod 2^BITS_PER_MPI_LIMB + * + * (1) Compute N^(-1) mod 2^BITS_PER_MPI_LIMB + * (2) Then, negate the value of (1) + * + * For computing N^(-1) mod (power of two), see: + * + * Jeffrey Hurchalla + * An Improved Integer Modular Multiplicative Inverse (modulo 2^w) + * https://arxiv.org/abs/2204.04342 + * + */ +static mpi_limb_t +compute_minv (mpi_limb_t n) +{ + mpi_limb_t x, y; + + gcry_assert (n%2 == 1); + + x = (3*n)^2; + y = 1 - n*x; + x = x*(1 + y); + y *= y; + x = x*(1 + y); + y *= y; + x = x*(1 + y); +#if BITS_PER_MPI_LIMB == 32 + return -x; +#elif BITS_PER_MPI_LIMB == 64 + y *= y; + x = x*(1 + y); + return -x; +#else +# error "Please implement multiplicative inverse mod power of 2" +#endif +} + + +/* + * Compute T * R^(-1) mod M (where R is represented by MINV) + * + * Reference: + * Handbook of Applied Cryptography + * Algorithm 14.82: Montgomery reduction + */ +static void +mont_reduc (mpi_ptr_t rp, mpi_ptr_t tp, + mpi_ptr_t mp, mpi_size_t n, mpi_limb_t minv) +{ + mpi_size_t i; + mpi_limb_t cy0; + mpi_limb_t cy1 = 0; + + for (i = 0; i < n; i++) + { + mpi_limb_t ui = tp[i] * minv; + + cy0 = _gcry_mpih_addmul_1 (tp + i, mp, n, ui); + cy1 += _gcry_mpih_add_1_lli (tp + n + i, n - i, cy0); + } + + cy0 = _gcry_mpih_sub_n (rp, tp + n, mp, n); + _gcry_mpih_set_cond (rp, tp + n, n, + mpih_limb_is_not_zero (cy0) + & mpih_limb_is_zero (cy1)); +} + +/* + * Compute X * Y * R^(-1) mod M (where R is represented by MINV) + * + * Reference: + * Handbook of Applied Cryptography + * Algorithm 14.86: Montgomery multiplication + * + * RP should have space of 2*N limbs. + * + */ +static void +mont_mul (mpi_ptr_t rp, mpi_ptr_t xp, mpi_ptr_t yp, mpi_ptr_t mp, + mpi_size_t n, mpi_limb_t minv, mpi_ptr_t scratch_2n) +{ + _gcry_mpih_mul_lli (scratch_2n, xp, n, yp, n); + mont_reduc (rp, scratch_2n, mp, n, minv); +} + +/* Determine the window size for computing exponentiation. */ +static int +window_size (mpi_size_t esize) +{ + int W; + +#if BITS_PER_MPI_LIMB <= 32 + if (esize > 24) + W = 5; + else if (esize > 16) + W = 4; + else if (esize > 12) + W = 3; + else if (esize > 8) + W = 2; + else + W = 1; + return W; +#else + if (esize > 8) + W = 4; + else if (esize > 6) + W = 3; + else if (esize > 4) + W = 2; + else + W = 1; + return W; +#endif + return W; +} + +/* + * Compute X ^ E mod M + * + * where X is in BP, M is in MP. + * The size of limbs for BP and MP are N. + * E is in EP, size of limbs EN. + * + * Result will be in RP with size N. + * + * Reference: + * Handbook of Applied Cryptography + * Algorithm 14.82: Left-to-right k-ary exponentiation + * Algorithm 14.94: Montgomery exponentiation + * + */ +void +_gcry_mpih_powm_lli (mpi_ptr_t rp, mpi_ptr_t bp, mpi_ptr_t mp, mpi_size_t n, + mpi_ptr_t ep, mpi_size_t en) +{ + mpi_size_t scratch_size; +#define temp0 (scratch) +#define temp2 (scratch+n*2) +#define a (scratch+n*4) +#define precomp (scratch+n*5) + mpi_ptr_t scratch; + mpi_limb_t minv; + mpi_size_t i; + int mod_shift_cnt; + int windowsize = window_size (en); + mpi_limb_t wmask = (((mpi_limb_t) 1 << windowsize) - 1); +#define temp1 (precomp+n) +#define x_tilde (precomp+n) + + scratch_size = (5 + (1 << windowsize))*n; + scratch = _gcry_mpi_alloc_limb_space (scratch_size, 1); + + minv = compute_minv (mp[0]); + + gcry_assert (mp[0]*(-minv) == 1); + + MPN_ZERO (temp0, n); + + /* TEMP0 := R mod m */ + count_leading_zeros (mod_shift_cnt, mp[n-1]); + if (mod_shift_cnt) + { + _gcry_mpih_lshift (temp2, mp, n, mod_shift_cnt); + temp0[n] = (mpi_limb_t)1 << mod_shift_cnt; + } + else + { + MPN_COPY (temp2, mp, n); + temp0[n] = 1; + } + _gcry_mpih_divrem (temp1, 0, temp0, n+1, temp2, n); + if (mod_shift_cnt) + _gcry_mpih_rshift (temp0, temp0, n, mod_shift_cnt); + /* PRECOMP[0] := R mod m */ + MPN_COPY (precomp, temp0, n); + + /* TEMP0 := (R mod m)^2 */ + _gcry_mpih_sqr_n_basecase (temp0, precomp, n); + + /* TEMP0 := R^2 mod m */ + if (mod_shift_cnt) + _gcry_mpih_lshift (temp0, temp0, n*2, mod_shift_cnt); + _gcry_mpih_divrem (temp1, 0, temp0, n*2, temp2, n); + if (mod_shift_cnt) + _gcry_mpih_rshift (temp0, temp0, n, mod_shift_cnt); + /* x~ := Mont(x, R^2 mod m) */ + mont_mul (x_tilde, bp, temp0, mp, n, minv, temp2); + + /* PRECOMP[i] := x~ ^ i */ + for (i = 0; i < (1 << windowsize) - 2; i += 2) + { + _gcry_mpih_sqr_n_basecase (temp0, precomp+n*(i/2+1), n); + mont_reduc (precomp+n*(i+2), temp0, mp, n, minv); + mont_mul (precomp+n*(i+3), x_tilde, precomp+n*(i+2), mp, n, minv, temp2); + } + + MPN_COPY (a, precomp, n); + i = en * BITS_PER_MPI_LIMB; + do + { + mpi_limb_t e; + int w; + + if (i < windowsize) + { + e = ep[0] & (((mpi_limb_t) 1 << i) - 1); + w = i; + i = 0; + } + else + { + mpi_limb_t v; + mpi_size_t shift; + mpi_size_t j; + int nbits_in_v; + + i -= windowsize; + j = i / BITS_PER_MPI_LIMB; + shift = i % BITS_PER_MPI_LIMB; + v = ep[j] >> shift; + nbits_in_v = BITS_PER_MPI_LIMB - shift; + if (nbits_in_v < windowsize) + v += ep[j + 1] << nbits_in_v; + e = v & wmask; + w = windowsize; + } + + do + { + _gcry_mpih_sqr_n_basecase (temp0, a, n); + mont_reduc (a, temp0, mp, n, minv); + } + while (--w); + + _gcry_mpih_table_lookup (temp0, precomp, n, (1 << windowsize), e); + mont_mul (a, a, temp0, mp, n, minv, temp2); + } + while (i); + + MPN_ZERO (temp0, n); + temp0[0] = 1; + mont_mul (a, a, temp0, mp, n, minv, temp2); + + MPN_COPY (rp, a, n); + _gcry_mpi_free_limb_space (scratch, scratch_size); +} diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h index d52a1b1b..1eb58cb9 100644 --- a/src/gcrypt-int.h +++ b/src/gcrypt-int.h @@ -474,6 +474,7 @@ void _gcry_mpi_mul_2exp (gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt); void _gcry_mpi_div (gcry_mpi_t q, gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor, int round); void _gcry_mpi_mod (gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor); +const char *_gcry_mpi_get_powm_config (void); void _gcry_mpi_powm (gcry_mpi_t w, const gcry_mpi_t b, const gcry_mpi_t e, const gcry_mpi_t m); diff --git a/src/global.c b/src/global.c index a5a48cb5..74cf16d3 100644 --- a/src/global.c +++ b/src/global.c @@ -378,6 +378,9 @@ print_config (const char *what, gpgrt_stream_t fp) if (!what || !strcmp (what, "mpi-asm")) gpgrt_fprintf (fp, "mpi-asm:%s:\n", _gcry_mpi_get_hw_config ()); + if (!what || !strcmp (what, "mpi-pow")) + gpgrt_fprintf (fp, "mpi-pow:%s\n", _gcry_mpi_get_powm_config ()); + if (!what || !strcmp (what, "hwflist")) { unsigned int hwfeatures, afeature; -- From jussi.kivilinna at iki.fi Fri Feb 14 09:35:58 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 14 Feb 2025 10:35:58 +0200 Subject: [PATCH] MPI helper of addition one limb, Least Leak Intended In-Reply-To: <877c5tqpuy.fsf@haruna.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <877c5tqpuy.fsf@haruna.fsij.org> Message-ID: On 14.2.2025 3.25, NIIBE Yutaka via Gcrypt-devel wrote: > Hello, > > This change introduces a function _gcry_mpih_add_1_lli for one limb > addition with least leak. > > diff --git a/mpi/mpi-inline.h b/mpi/mpi-inline.h > index 090e8a94..6954affb 100644 > --- a/mpi/mpi-inline.h > +++ b/mpi/mpi-inline.h > @@ -68,6 +68,28 @@ _gcry_mpih_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, > } > > > +/* Do same calculation as _gcry_mpih_add_1 does (under the condition > + of RES_PTR == S1_PTR), Least Leak Intended. */ > +static inline mpi_limb_t > +_gcry_mpih_add_1_lli (mpi_ptr_t s1_ptr, mpi_size_t s1_size, mpi_limb_t s2_limb) > +{ > + mpi_limb_t x; > + mpi_limb_t cy; > + > + x = *s1_ptr; > + s2_limb += x; > + *s1_ptr++ = s2_limb; > + cy = (s2_limb < x); > + while ( --s1_size ) > + { > + x = *s1_ptr + cy; > + *s1_ptr++ = x; > + cy = mpih_limb_is_zero (x) & mpih_limb_is_not_zero (cy); > + } > + > + return cy; I think this function could use 'add_ssaaaa' macro to handle addition with carry. Something like this (completely untested): cy = s2_limb; while ( s1_size ) { x = *s1_ptr; add_ssaaaa(cy, x, 0, cy, 0, x); *s1_ptr++ = x; s1_size--; } return cy; -Jussi From lucas.mulling at suse.com Fri Feb 14 14:48:52 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Fri, 14 Feb 2025 10:48:52 -0300 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: <87ikpdqt7h.fsf@haruna.fsij.org> References: <8734gjfu2k.fsf@jacob.g10code.de> <875xldeqz4.fsf@jacob.g10code.de> <87ikpdqt7h.fsf@haruna.fsij.org> Message-ID: Hello, On Thu Feb 13, 2025 at 9:13 PM -03, NIIBE Yutaka wrote: > Hello, > > I pushed the changes by Lucas Mulling as the commit of: > > 13a71215c255377863b0154ac602c86fe5450c49 > > If there are changes needed for the service indicator, please let us > know. Thank you, and Werner. I have on more patch series for non-compliant sexp flags, but I'll wait for reviewer as a few things are still open. I think that should be all for the fips revamp then. From gniibe at fsij.org Mon Feb 17 06:23:17 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Mon, 17 Feb 2025 14:23:17 +0900 Subject: [PATCH] MPI helper of comparison, Least Leak Intended In-Reply-To: <87frkk2etg.fsf@haruna.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <87plju492s.fsf@akagi.fsij.org> <87frkpmbsb.fsf@haruna.fsij.org> <89b5ea2f-03b5-43cb-ad85-645ccdb42c60@gmail.com> <87frkk2etg.fsf@haruna.fsij.org> Message-ID: <87frkdta9m.fsf@haruna.fsij.org> NIIBE Yutaka wrote: > Jussi Kivilinna wrote: >> int >> _gcry_mpih_cmp_lli (mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) >> { >> mpi_size_t i; >> mpi_limb_t res_gt = 0; >> mpi_limb_t res_lt = 0; >> >> for (i = 0; i < size ; i++) >> { >> mpi_limb_t gt, lt, eq, neq; >> gt = mpih_ct_limb_greater_than (up[i], vp[i]); >> lt = mpih_ct_limb_less_than (up[i], vp[i]); >> neq = ct_limb_gen_mask(gt | lt); >> eq = ct_limb_gen_inv_mask(gt | lt); >> res_gt = (eq & res_gt) | (neq & gt); >> res_lt = (eq & res_lt) | (neq & lt); >> } >> >> return (int)(res_gt - res_lt); /* return 0 if U==V, 1 if U>V, -1 if U> } > > Please apply and push this version, because it's the way the function > name suggests (returning -1, 0, 1). I'm going to push this implementation to master. -- From gniibe at fsij.org Mon Feb 17 06:26:56 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Mon, 17 Feb 2025 14:26:56 +0900 Subject: [PATCH] MPI helper of addition one limb, Least Leak Intended In-Reply-To: References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <877c5tqpuy.fsf@haruna.fsij.org> Message-ID: <87cyfhta3j.fsf@haruna.fsij.org> Hello, Jussi, Jussi Kivilinna wrote: > I think this function could use 'add_ssaaaa' macro to handle addition with > carry. > > Something like this (completely untested): > > cy = s2_limb; > while ( s1_size ) > { > x = *s1_ptr; > add_ssaaaa(cy, x, 0, cy, 0, x); > *s1_ptr++ = x; > s1_size--; > } > return cy; Good. I'm going to push this to master for _gcry_mpih_add_1_lli function. Further, I'm goint to push the chnage for _gcry_mpih_add_lli function as: mpi_limb_t _gcry_mpih_add_lli (mpi_ptr_t wp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t usize) { mpi_size_t i; mpi_limb_t cy; cy = 0; for (i = 0; i < usize; i++) { mpi_limb_t u = up[i]; mpi_limb_t v = vp[i]; mpi_limb_t w; add_ssaaaa (cy, w, 0, u, 0, cy); add_ssaaaa (cy, w, cy, w, 0, v); wp[i] = w; } return cy; } -- From gniibe at fsij.org Mon Feb 17 06:38:32 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Mon, 17 Feb 2025 14:38:32 +0900 Subject: (EC)DSA signature generation constant-time (not depend value of K) Message-ID: <87a5alt9k7.fsf@haruna.fsij.org> Hello, For (EC)DSA signature generation, I created a ticket: https://dev.gnupg.org/T7519 And added some patches (including some *_lli routines). Here are more patches to be applied on top of master commit of: 58e72af4eac4711993191919b6890b5ebb554acc Major improvement for least leak might be the change of _gcry_dsa_modify_k. _gcry_dsa_modify_k was introduced for original Minerva attack so that the length of limbs for K is always same size, but use of mpi_add in the routine becomes the source of the signal for K. -- -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-cipher-EC-DSA-Fix-_gcry_dsa_modify_k-to-least-leak.patch Type: text/x-diff Size: 1585 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0002-cipher-EC-DSA-Avoid-MPI-normalize-by-mpi_rshift.patch Type: text/x-diff Size: 1270 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0003-cipher-EC-DSA-Fix-_gcry_dsa_gen_-k-not-to-normalize-.patch Type: text/x-diff Size: 1636 bytes Desc: not available URL: From gniibe at fsij.org Tue Feb 18 06:30:49 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 18 Feb 2025 14:30:49 +0900 Subject: [PATCH] MPI helper of table lookup, Least Leak Intended In-Reply-To: References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <874j0xqfvg.fsf@haruna.fsij.org> Message-ID: <87wmdnlsza.fsf@haruna.fsij.org> Hello, Thank you for your comments. Jacob Bachmeyer wrote: > The obvious comment to me is that the function name should probably > contain either "_ct" or "_lli" to denote that this is a slow function > for leak minimization. Ack. I have a look at OpenSSL and GNU MP. OpenSSL has: static ossl_inline void constant_time_lookup(void *out, const void *table, size_t rowsize, size_t numrows, size_t idx); GNU MP has: void mpn_sec_tabselect (volatile mp_limb_t *rp, volatile const mp_limb_t *tab, mp_size_t n, mp_size_t nents, mp_size_t which); Thus, I'm going to use the name "_gcry_mpih_lookup_lli" for libgcrypt, adding _lli suffix and removing "table" since it can be easy to assume. > There might also be architecture-specific instructions that can be used > to retrieve a table row without polluting the data cache; allowing > architecture-specific overrides here could make a very significant > performance difference, as the basic implementation could easily flush > the entire data cache if used on a large table. > > For the base case, reading the entire table is probably the best that > you can do, but if you have a "load without temporal locality" > instruction (I believe that there are such instructions in SSE, for > example), you can avoid the problem, while accessing only a single table > row.? (The memory bus is assumed to not be visible to an attacker.) Ah, I didn't consider that. IIUC, you mean something like _mm*_stream_load_si* functions in the Intel Intrinsics Guide (to access an entry in a table). https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#cats=Load That is interesting to try, and it could be effective when table is larger and read-only. (But when table is larger than a page, it might be a target of TLB flush attack to determine which page.) Note that in this particular case of the modular exponentiation, the table size is typically 4 Ki-byte and the entry size is 256-byte. The table is computed in _gcry_mpih_powm_lli before the loop which uses the table. For now, let me apply and push _gcry_mpih_lookup_lli, and possible improvement will be done in future. -- From jussi.kivilinna at iki.fi Tue Feb 18 09:48:01 2025 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 18 Feb 2025 10:48:01 +0200 Subject: [PATCH] MPI helper of addition one limb, Least Leak Intended In-Reply-To: <87cyfhta3j.fsf@haruna.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <877c5tqpuy.fsf@haruna.fsij.org> <87cyfhta3j.fsf@haruna.fsij.org> Message-ID: Hello, On 2025-02-17 07:26, NIIBE Yutaka via Gcrypt-devel wrote: > Hello, Jussi, > > Jussi Kivilinna wrote: >> I think this function could use 'add_ssaaaa' macro to handle addition >> with >> carry. >> >> Something like this (completely untested): >> >> cy = s2_limb; >> while ( s1_size ) >> { >> x = *s1_ptr; >> add_ssaaaa(cy, x, 0, cy, 0, x); >> *s1_ptr++ = x; >> s1_size--; >> } >> return cy; > > Good. I'm going to push this to master for _gcry_mpih_add_1_lli > function. > > Further, I'm goint to push the chnage for _gcry_mpih_add_lli > function as: Is LLI variant really needed? This looks the same as the _gcry_mpih_add_n. The assembly versions of this (for select architectures) should all be constant time. Well, looking at some of those implementations, they look overly complex and we carry assembly implementations for now old/obsolete architectures. I think we should remove obsolete ones in favor of just using the generic version. I'd just keep assembly for following architectures: - amd64 - i386 - aarch64 - arm - generic We could then validate that these really have constant time (or LLI) implementations. -Jussi > > mpi_limb_t > _gcry_mpih_add_lli (mpi_ptr_t wp, mpi_ptr_t up, mpi_ptr_t vp, > mpi_size_t usize) > { > mpi_size_t i; > mpi_limb_t cy; > > cy = 0; > for (i = 0; i < usize; i++) > { > mpi_limb_t u = up[i]; > mpi_limb_t v = vp[i]; > mpi_limb_t w; > > add_ssaaaa (cy, w, 0, u, 0, cy); > add_ssaaaa (cy, w, cy, w, 0, v); > wp[i] = w; > } > > return cy; > } From jcb62281 at gmail.com Wed Feb 19 02:03:31 2025 From: jcb62281 at gmail.com (Jacob Bachmeyer) Date: Tue, 18 Feb 2025 19:03:31 -0600 Subject: [PATCH] MPI helper of table lookup, Least Leak Intended In-Reply-To: <87wmdnlsza.fsf@haruna.fsij.org> References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <874j0xqfvg.fsf@haruna.fsij.org> <87wmdnlsza.fsf@haruna.fsij.org> Message-ID: On 2/17/25 23:30, NIIBE Yutaka wrote: > Hello, > > Thank you for your comments. You are welcome. > Jacob Bachmeyer wrote: > [...] > >> There might also be architecture-specific instructions that can be used >> to retrieve a table row without polluting the data cache; allowing >> architecture-specific overrides here could make a very significant >> performance difference, as the basic implementation could easily flush >> the entire data cache if used on a large table. >> >> For the base case, reading the entire table is probably the best that >> you can do, but if you have a "load without temporal locality" >> instruction (I believe that there are such instructions in SSE, for >> example), you can avoid the problem, while accessing only a single table >> row.? (The memory bus is assumed to not be visible to an attacker.) > Ah, I didn't consider that. > > IIUC, you mean something like _mm*_stream_load_si* functions in the > Intel Intrinsics Guide (to access an entry in a table). > > https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#cats=Load Those, and analogous instructions on other architectures. > That is interesting to try, and it could be effective when table is > larger and read-only. (But when table is larger than a page, > it might be a target of TLB flush attack to determine which page.) > > Note that in this particular case of the modular exponentiation, the > table size is typically 4 Ki-byte and the entry size is 256-byte. The > table is computed in _gcry_mpih_powm_lli before the loop which uses the > table. So, for the initial case, simply ensure that the table is page-aligned and TLB leaks are solved, since the table is exactly one page. Exactly one page is also very unlikely to have significant impact on the effectiveness of the data cache, since every modern processor that I have seen has L1 caches much larger than 4KiB. I believe that there are also prefetch instructions that would force TLB entries to be allocated, or "non-temporal" accesses might also have their own TLB. > For now, let me apply and push _gcry_mpih_lookup_lli, and > possible improvement will be done in future. You should probably add comments noting this caveat that the LLI table select will read the entire table into the data cache, which is fine for very small tables but could be very slow if used with a larger table. This (holding the entire table in the data cache) might actually be beneficial, since it avoids the possibility of cache misses introducing timing leaks. Just be sure to document the caveat that the table size must be carefully limited. -- Jacob -------------- next part -------------- An HTML attachment was scrubbed... URL: From gniibe at fsij.org Wed Feb 19 02:29:45 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 19 Feb 2025 10:29:45 +0900 Subject: [PATCH] MPI helper of addition one limb, Least Leak Intended In-Reply-To: References: <877c6b8pp8.fsf@akagi.fsij.org> <87seovj2cn.fsf@akagi.fsij.org> <877c5tqpuy.fsf@haruna.fsij.org> <87cyfhta3j.fsf@haruna.fsij.org> Message-ID: <87frkazppy.fsf@haruna.fsij.org> Hello, Jussi Kivilinna wrote: > Is LLI variant really needed? This looks the same as the > _gcry_mpih_add_n. You are right. It is not needed, actually. I overlooked. I'm going to fix it by: #define _gcry_mpih_add_lli _gcry_mpih_add_n > I think we should remove obsolete ones in favor of just using the > generic > version. I'd just keep assembly for following architectures: > - amd64 > - i386 > - aarch64 > - arm > - generic > > We could then validate that these really have constant time (or LLI) > implementations. Agreed. For the schedule, I think it should be done for 1.12. I don't think this kind of removal/cleanup is not needed for next revision (1.11.1). -- From gniibe at fsij.org Wed Feb 19 03:07:26 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 19 Feb 2025 11:07:26 +0900 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: References: <8734gjfu2k.fsf@jacob.g10code.de> <875xldeqz4.fsf@jacob.g10code.de> <87ikpdqt7h.fsf@haruna.fsij.org> Message-ID: <87cyfeznz5.fsf@haruna.fsij.org> Hello, "Lucas Mulling" wrote: > I have on more patch series for non-compliant > sexp flags, but I'll wait for reviewer as a few things are still open. I > think that should be all for the fips revamp then. Thank you for your waiting and cooperation for serializing our development process. By the commit of today (2025-02-19): 58aca75a295d6ef66ac7b97093144c0855b6ea4f Recent changes have all pushed to the repo. Please post your changes now. -- From lucas.mulling at suse.com Wed Feb 19 15:10:43 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Wed, 19 Feb 2025 11:10:43 -0300 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: <87cyfeznz5.fsf@haruna.fsij.org> References: <8734gjfu2k.fsf@jacob.g10code.de> <875xldeqz4.fsf@jacob.g10code.de> <87ikpdqt7h.fsf@haruna.fsij.org> <87cyfeznz5.fsf@haruna.fsij.org> Message-ID: Hello, > I pushed the changes by Lucas Mulling as the commit of: > > 13a71215c255377863b0154ac602c86fe5450c49 On Tue Feb 18, 2025 at 11:07 PM -03, NIIBE Yutaka wrote: > Thank you for your waiting and cooperation for serializing our > development process. > > By the commit of today (2025-02-19): > > 58aca75a295d6ef66ac7b97093144c0855b6ea4f > > Recent changes have all pushed to the repo. Please post your changes now. Sorry about the confusion, but I only see one patch applied, the series to differentiate SHA1 consists of two patches (attached to the first message of this thread): * 0001-md-Make-SHA1-non-FIPS-and-differentiate-in-the-SLI.patch * 0002-cipher-Differentiate-SHA1-with-GCRY_FIPS_FLAG_REJECT_MD_SHA1.patch Again, sorry for sending patches like this as my corporate email was not working with git. Thank you! From gniibe at fsij.org Thu Feb 20 08:08:45 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 20 Feb 2025 16:08:45 +0900 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: References: <8734gjfu2k.fsf@jacob.g10code.de> <875xldeqz4.fsf@jacob.g10code.de> <87ikpdqt7h.fsf@haruna.fsij.org> <87cyfeznz5.fsf@haruna.fsij.org> Message-ID: <87msehks8y.fsf@haruna.fsij.org> Hello, Sorry for my overlooking of your patches in previous message. I only looked and pushed the first of patches. That's my mistake. Looking the two patches, I realized that there are three different purposes in those patches. (1) Fixing the behaviour of gcry_pk_sign and gcry_pk_verify. (2) Introduction of GCRY_FIPS_FLAG_REJECT_MD_SHA1, so that application can reject use of SHA1 (even if it's approved hash function at the time of execution). (3) Deprecating SHA-1 for FIPS mode to prepare future when it will be not approved hash function. Shall we make three different patches for those? To make commits record straight (for the situation when we will check in future), I would like to revert your change of 0001-md-Make-SHA1-non-FIPS-and-differentiate-in-the-SLI.patch And then, apply those three patches, step-by-step. Firstly, let us focus and fix for (1). (In my opinion, (2) and (3) can be deferred.) In 1.10, gcry_pk_sign and gcry_pk_verify are not supported under FIPS mode. gcry_pk_hash_sign and gcry_pk_hash_verify are supported, instead. IIRC, this is to ensure rejecting use of SHA1 in digital signature under FIPS mode. With service indicator revamp, there are valid use cases where gcry_pk_sign and gcry_pk_verify can be used under FIPS mode. But, it's buggy now. Use of SHA1 should be marked/rejected with gcry_pk_sign and gcry_pk_verify. -- From gniibe at fsij.org Fri Feb 21 06:38:27 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 21 Feb 2025 14:38:27 +0900 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: <87msehks8y.fsf@haruna.fsij.org> References: <8734gjfu2k.fsf@jacob.g10code.de> <875xldeqz4.fsf@jacob.g10code.de> <87ikpdqt7h.fsf@haruna.fsij.org> <87cyfeznz5.fsf@haruna.fsij.org> <87msehks8y.fsf@haruna.fsij.org> Message-ID: <877c5jyi0c.fsf@haruna.fsij.org> Hello, NIIBE Yutaka wrote: > (1) Fixing the behaviour of gcry_pk_sign and gcry_pk_verify. Here is a patch fixing gcry_pk_sign and gcry_pk_verify. I'm not sure if allowing use of gcry_pk_sign and gcry_pk_verify is good/bad under FIPS mode since hashing is done beforehand with RSA and ECDSA. -- -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-cipher-rsa-Mark-reject-SHA1-unknown-with-RSA-signatu.patch Type: text/x-diff Size: 22904 bytes Desc: not available URL: From gniibe at fsij.org Tue Feb 25 08:46:37 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 25 Feb 2025 16:46:37 +0900 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: <877c5jyi0c.fsf@haruna.fsij.org> References: <8734gjfu2k.fsf@jacob.g10code.de> <875xldeqz4.fsf@jacob.g10code.de> <87ikpdqt7h.fsf@haruna.fsij.org> <87cyfeznz5.fsf@haruna.fsij.org> <87msehks8y.fsf@haruna.fsij.org> <877c5jyi0c.fsf@haruna.fsij.org> Message-ID: <87jz9eh3fm.fsf@haruna.fsij.org> NIIBE Yutaka wrote: >> (1) Fixing the behaviour of gcry_pk_sign and gcry_pk_verify. > > Here is a patch fixing gcry_pk_sign and gcry_pk_verify. Here is another fix for gcry_md_algo_info. Applying two patches for gcry_pk_sign and gcry_pk_verify and then gcry_md_algo_info, we can go SHA1 deprecation changes. BTW, I realized that I misunderstood about GCRY_FIPS_FLAG_REJECT_MD_SHA1. IIUC, it's similar to GCRY_FIPS_FLAG_REJECT_MD_MD5 (MD5 is deprecated, but allow non-rejection behavior). SHA1 deprecation changes includes: * Fixes of tests/* * Introduction of GCRY_FIPS_FLAG_REJECT_MD_SHA1 * Change to cipher/sha1.c ========================= @@ -759,7 +759,7 @@ static const gcry_md_oid_spec_t oid_spec_sha1[] = const gcry_md_spec_t _gcry_digest_spec_sha1 = { - GCRY_MD_SHA1, {0, 1}, + GCRY_MD_SHA1, {0, 0}, "SHA1", asn, DIM (asn), oid_spec_sha1, 20, sha1_init, _gcry_md_block_write, sha1_final, sha1_read, NULL, _gcry_sha1_hash_buffers, ========================= Let me try fixing tests/*, firstly. -- -------------- next part -------------- A non-text attachment was scrubbed... Name: 0003-md-Fix-gcry_md_algo_info-to-mark-reject-under-FIPS-m.patch Type: text/x-diff Size: 2029 bytes Desc: not available URL: From gniibe at fsij.org Wed Feb 26 06:16:54 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 26 Feb 2025 14:16:54 +0900 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: <87jz9eh3fm.fsf@haruna.fsij.org> References: <8734gjfu2k.fsf@jacob.g10code.de> <875xldeqz4.fsf@jacob.g10code.de> <87ikpdqt7h.fsf@haruna.fsij.org> <87cyfeznz5.fsf@haruna.fsij.org> <87msehks8y.fsf@haruna.fsij.org> <877c5jyi0c.fsf@haruna.fsij.org> <87jz9eh3fm.fsf@haruna.fsij.org> Message-ID: <8734g12sl5.fsf@haruna.fsij.org> NIIBE Yutaka wrote: > Here is another fix for gcry_md_algo_info. This is not enough. Fixing _gcry_md_selftest is needed. Attached is a patch for that. -- -------------- next part -------------- A non-text attachment was scrubbed... Name: 0004-md-Use-check_digest_algo_spec-in-_gcry_md_selftest.patch Type: text/x-diff Size: 1793 bytes Desc: not available URL: From gniibe at fsij.org Wed Feb 26 06:24:07 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 26 Feb 2025 14:24:07 +0900 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: <87jz9eh3fm.fsf@haruna.fsij.org> References: <8734gjfu2k.fsf@jacob.g10code.de> <875xldeqz4.fsf@jacob.g10code.de> <87ikpdqt7h.fsf@haruna.fsij.org> <87cyfeznz5.fsf@haruna.fsij.org> <87msehks8y.fsf@haruna.fsij.org> <877c5jyi0c.fsf@haruna.fsij.org> <87jz9eh3fm.fsf@haruna.fsij.org> Message-ID: <871pvl2s94.fsf@haruna.fsij.org> NIIBE Yutaka wrote: > Let me try fixing tests/*, firstly. When SHA1 will be deprecated, for signing, tests/basic.c, tests/pubkey.c, and tests/t-fips-service-ind.c should be updated. This one is for KDF with SHA1. -- -------------- next part -------------- A non-text attachment was scrubbed... Name: 0005-tests-Update-t-fips-service-ind-using-GCRY_MD_SHA256.patch Type: text/x-diff Size: 3251 bytes Desc: not available URL: From gniibe at fsij.org Wed Feb 26 06:37:01 2025 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 26 Feb 2025 14:37:01 +0900 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: <871pvl2s94.fsf@haruna.fsij.org> References: <8734gjfu2k.fsf@jacob.g10code.de> <875xldeqz4.fsf@jacob.g10code.de> <87ikpdqt7h.fsf@haruna.fsij.org> <87cyfeznz5.fsf@haruna.fsij.org> <87msehks8y.fsf@haruna.fsij.org> <877c5jyi0c.fsf@haruna.fsij.org> <87jz9eh3fm.fsf@haruna.fsij.org> <871pvl2s94.fsf@haruna.fsij.org> Message-ID: <87wmdd1d36.fsf@haruna.fsij.org> Hello, This is the last one to make SHA1 non-FIPS. But, I hesitate to apply this for 1.11. I feel that it's good to create a branch for 1.11 and apply this to master, and then continue on updating tests/basic.c, tests/pkcs1v2.c, etc to be 1.12. If we agree, let us push patches so far except this one to master, and create a branch of 1.11 (LIBGCRYPT-1.11-BRANCH). -- -------------- next part -------------- A non-text attachment was scrubbed... Name: 0006-md-Make-SHA-1-non-FIPS.patch Type: text/x-diff Size: 6055 bytes Desc: not available URL: From lucas.mulling at suse.com Wed Feb 26 16:29:52 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Wed, 26 Feb 2025 12:29:52 -0300 Subject: [PATCH 0/2] KAT for non-deterministic ECDSA and differentiate K Message-ID: <20250226153056.156673-1-lucas.mulling@suse.com> Currently, the KAT for ECDSA only tests for deterministic ECDSA with rfc6979 flag. For FIPS, a test for non-deterministic ECDSA is also required, this is achieved by setting the k with label. Also, in FIPS mode, label is not allowed and needs to be differentiate. Lucas Mulling (2): cipher: Add KAT for non-rfc6979 ECDSA with fixed k cipher: Differentiate use of label K in the SLI cipher/ecc.c | 69 ++++++++++++++++++++++++++++++++++---- src/gcrypt.h.in | 1 + tests/t-fips-service-ind.c | 10 +++--- 3 files changed, 69 insertions(+), 11 deletions(-) -- 2.48.1 From lucas.mulling at suse.com Wed Feb 26 16:29:53 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Wed, 26 Feb 2025 12:29:53 -0300 Subject: [PATCH 1/2] cipher: Add KAT for non-rfc6979 ECDSA with fixed k In-Reply-To: <20250226153056.156673-1-lucas.mulling@suse.com> References: <20250226153056.156673-1-lucas.mulling@suse.com> Message-ID: <20250226153056.156673-2-lucas.mulling@suse.com> * cipher/ecc.c (run_selftests): Implement KAT for non-deterministic ECDSA. * cipher/ecc. (rfc6979_ecdsa_sample_data, rfc6979_ecdsa_sample_data_bad, rfc6979_ecdsa_data_tmpl): New. Signed-off-by: Lucas Mulling --- cipher/ecc.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/cipher/ecc.c b/cipher/ecc.c index 525523ed..82630dac 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -73,7 +73,6 @@ static const char *ecc_names[] = NULL, }; - /* Sample NIST P-256 key from RFC 6979 A.2.5 */ static const char ecdsa_sample_public_key_secp256[] = "(public-key" @@ -93,24 +92,48 @@ static const char ecdsa_sample_secret_key_secp256[] = /**/ "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)))"; /* Sample data from RFC 6979 section A.2.5, hash is of message "sample" */ -static const char ecdsa_sample_data[] = +static const char rfc6979_ecdsa_sample_data[] = "(data (flags rfc6979 prehash)" " (hash-algo sha256)" " (value 6:sample))"; -static const char ecdsa_sample_data_bad[] = +static const char rfc6979_ecdsa_sample_data_bad[] = "(data (flags rfc6979)" " (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915" /**/ "62113d8a62add1bf#))"; +static const char *rfc6979_ecdsa_data_tmpl = + "(data (flags rfc6979)" + " (hash %s %b))"; + +/* + * Sample data from RFC 6979 section A.2.5, with fixed k, + * hash is of message "sample". + */ +static const char ecdsa_sample_data[] = + "(data (flags raw prehash)" + " (label #A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60#)" + " (hash-algo sha256)" + " (value 6:sample))"; + +static const char ecdsa_sample_data_bad[] = + "(data (flags raw)" + " (label #A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60#)" + " (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915" + /**/ "62113d8a62add1bf#))"; + +static const char *ecdsa_data_tmpl = + "(data (flags raw)" + " (label #A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60#)" + " (hash %s %b))"; + static const char ecdsa_signature_r[] = "efd48b2aacb6a8fd1140dd9cd45e81d69d2c877b56aaf991c34d0ea84eaf3716"; static const char ecdsa_signature_s[] = "f7cb1c942d657c41d436c7a1b6e29f65f3e900dbb9aff4064dc4ab2f843acda8"; -static const char *ecdsa_data_tmpl = "(data (flags rfc6979) (hash %s %b))"; -/* Sample data from RFC 6979 section A.2.5, hash is of message "sample" */ + /* Sample data from RFC 6979 section A.2.5, hash is of message "sample" */ static const char ecdsa_sample_data_string[] = "sample"; static const char ecdsa_sample_data_bad_string[] = "sbmple"; @@ -2409,6 +2432,16 @@ run_selftests (int algo, int extended, selftest_report_func_t report) if (r) return r; + r = selftests_ecc (report, extended, 0, + ecdsa_sample_secret_key_secp256, + ecdsa_sample_public_key_secp256, + rfc6979_ecdsa_sample_data, rfc6979_ecdsa_sample_data_bad, + rfc6979_ecdsa_data_tmpl, + ecdsa_sample_data_string, ecdsa_sample_data_bad_string, + ecdsa_signature_r, ecdsa_signature_s); + if (r) + return r; + r = selftests_ecc (report, extended, 1, ed25519_sample_secret_key, ed25519_sample_public_key, -- 2.48.1 From lucas.mulling at suse.com Wed Feb 26 16:29:54 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Wed, 26 Feb 2025 12:29:54 -0300 Subject: [PATCH 2/2] cipher: Differentiate use of label K in the SLI In-Reply-To: <20250226153056.156673-1-lucas.mulling@suse.com> References: <20250226153056.156673-1-lucas.mulling@suse.com> Message-ID: <20250226153056.156673-3-lucas.mulling@suse.com> * cipher/ecc.c (ecc_sign, ecc_verify): Use of label K is not allowed in fips mode, differentiate with the GCRY_FIPS_FLAG_REJECT_PK_ECC_K flag. * src/gcrypt.h.in: New GCRY_FIPS_FLAG_REJECT_PK_ECC_K. * tests/t-fips-service-ind.c (check_pk_hash_sign_verify): Mark non compliant use of label. Signed-off-by: Lucas Mulling --- cipher/ecc.c | 26 +++++++++++++++++++++++++- src/gcrypt.h.in | 1 + tests/t-fips-service-ind.c | 10 +++++----- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/cipher/ecc.c b/cipher/ecc.c index 82630dac..5c6b609f 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -960,7 +960,16 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) log_mpidump ("ecc_sign data", data); if (ctx.label) - rc = _gcry_mpi_scan (&k, GCRYMPI_FMT_USG, ctx.label, ctx.labellen, NULL); + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK_ECC_K)) + { + rc = GPG_ERR_INV_DATA; + goto leave; + } + else + fips_service_indicator_mark_non_compliant (); + rc = _gcry_mpi_scan (&k, GCRYMPI_FMT_USG, ctx.label, ctx.labellen, NULL); + } if (rc) goto leave; @@ -1117,6 +1126,21 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx); if (rc) goto leave; + + if(ctx.label) + { + if (fips_mode ()) + { + if(fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK_ECC_K)) + { + rc = GPG_ERR_INV_DATA; + goto leave; + } + else + fips_service_indicator_mark_non_compliant (); + } + } + if (DBG_CIPHER) log_mpidump ("ecc_verify data", data); diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 3a7acb13..ce1b729d 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1990,6 +1990,7 @@ char *gcry_get_config (int mode, const char *what); #define GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2 (1 << 7) #define GCRY_FIPS_FLAG_REJECT_CIPHER_MODE (1 << 8) #define GCRY_FIPS_FLAG_REJECT_MD_SHA1 (1 << 9) +#define GCRY_FIPS_FLAG_REJECT_PK_ECC_K (1 << 10) #define GCRY_FIPS_FLAG_REJECT_MD \ (GCRY_FIPS_FLAG_REJECT_MD_MD5 | GCRY_FIPS_FLAG_REJECT_MD_OTHERS) diff --git a/tests/t-fips-service-ind.c b/tests/t-fips-service-ind.c index f8485176..d866b9d8 100644 --- a/tests/t-fips-service-ind.c +++ b/tests/t-fips-service-ind.c @@ -437,7 +437,7 @@ check_pk_hash_sign_verify (void) "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))", "(data(flags raw)(hash %s %b)(label %b))", "94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de", - 0, 0 + 1, 0, } }; int tvidx; @@ -536,7 +536,7 @@ check_pk_hash_sign_verify (void) if (ec == GPG_ERR_INV_OP) { /* libgcrypt is old, no support of the FIPS service indicator. */ - fail ("gcry_pk_hash test %d unexpectedly failed to check the FIPS service indicator.\n", + fail ("gcry_pk_hash_sign test %d unexpectedly failed to check the FIPS service indicator.\n", tvidx); goto next; } @@ -544,7 +544,7 @@ check_pk_hash_sign_verify (void) if (in_fips_mode && !tv[tvidx].expect_failure && ec) { /* Success with the FIPS service indicator == 0 expected, but != 0. */ - fail ("gcry_pk_hash test %d unexpectedly set the indicator in FIPS mode.\n", + fail ("gcry_pk_hash_sign test %d unexpectedly set the indicator in FIPS mode.\n", tvidx); goto next; } @@ -568,7 +568,7 @@ check_pk_hash_sign_verify (void) if (ec == GPG_ERR_INV_OP) { /* libgcrypt is old, no support of the FIPS service indicator. */ - fail ("gcry_pk_hash test %d unexpectedly failed to check the FIPS service indicator.\n", + fail ("gcry_pk_hash_verify test %d unexpectedly failed to check the FIPS service indicator.\n", tvidx); goto next; } @@ -576,7 +576,7 @@ check_pk_hash_sign_verify (void) if (in_fips_mode && !tv[tvidx].expect_failure && ec) { /* Success with the FIPS service indicator == 0 expected, but != 0. */ - fail ("gcry_pk_hash test %d unexpectedly set the indicator in FIPS mode.\n", + fail ("gcry_pk_hash_verify test %d unexpectedly set the indicator in FIPS mode.\n", tvidx); goto next; } -- 2.48.1 From lucas.mulling at suse.com Wed Feb 26 21:19:21 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Wed, 26 Feb 2025 17:19:21 -0300 Subject: [PATCH 0/4] Differentiate use of non-compliant flags in the SLI Message-ID: <20250226202131.381279-1-lucas.mulling@suse.com> FIPS requires that the following flags be differentiated in the SLI: * igninvflag; * no-blinding; * random-override. Lucas Mulling (4): cipher: Differentiate igninvflag in the SLI cipher: Differentiate no-blinding flag in the SLI cipher,visibility: Differentiate use of random-override in the SLI tests: Fix tests to account for differentiated flags cipher/pubkey-util.c | 45 +++++++++++++++++++++++++++++++- cipher/rsa.c | 30 +++++++++++++++++++-- src/visibility.c | 13 ++++++++++ tests/basic.c | 47 +++++++++++++++++++-------------- tests/pkcs1v2.c | 23 ++++++++++++++--- tests/t-dsa.c | 4 +++ tests/t-ecdsa.c | 4 +++ tests/t-ed25519.c | 4 +++ tests/t-ed448.c | 7 +++++ tests/t-fips-service-ind.c | 53 +++++++++++++++++++++++++++++--------- tests/t-rsa-pss.c | 4 +++ 11 files changed, 197 insertions(+), 37 deletions(-) -- 2.48.1 From lucas.mulling at suse.com Wed Feb 26 21:19:25 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Wed, 26 Feb 2025 17:19:25 -0300 Subject: [PATCH 4/4] tests: Fix tests to account for differentiated flags In-Reply-To: <20250226202131.381279-1-lucas.mulling@suse.com> References: <20250226202131.381279-1-lucas.mulling@suse.com> Message-ID: <20250226202131.381279-5-lucas.mulling@suse.com> * tests/basic.c (check_one_cipher, check_pubkey_sign, check_pubkey_sign_ecdsa): Fix formatting, include test index in fail print, mark tests that use random-override with FLAG_NOFIPS, as random-override is not allowed in fips mode. * tests/pkcs1v2.c (check_oaep, check_pss, check_v15crypt): Skip tests that use random-override. * tests/t-dsa.c (one_test_sexp): Skip tests that set the RSA salt in fips mode. Setting the rsa salt is not allowed in fips mode. * tests/t-ecdsa.c (one_test_sexp): Skip tests that set the salt in fips mode. Setting the salt is not allowed in fips mode. * tests/t-ed25519.c (one_test): Skip tests that set the salt in fips mode. Setting the salt is not allowed in fips mode. * tests/t-ed448.c (one_test): Skip tests that set the salt in fips mode. Setting the salt is not allowed in fips mode. * tests/t-fips-service-ind.c (check_pk_g_t_n_c, check_pk_hash_sign_verify): Check for correct differentiation of igninvflag, the flag itself does nothing but its not allowed in fips mode. * tests/t-rsa-pss.c (one_test_sexp): Skip tests that set the RSA salt in fips mode. Setting the RSA salt is not allowed in fips mode. Signed-off-by: Lucas Mulling --- tests/basic.c | 47 +++++++++++++++++++-------------- tests/pkcs1v2.c | 23 ++++++++++++++--- tests/t-dsa.c | 4 +++ tests/t-ecdsa.c | 4 +++ tests/t-ed25519.c | 4 +++ tests/t-ed448.c | 7 +++++ tests/t-fips-service-ind.c | 53 +++++++++++++++++++++++++++++--------- tests/t-rsa-pss.c | 4 +++ 8 files changed, 112 insertions(+), 34 deletions(-) diff --git a/tests/basic.c b/tests/basic.c index f32e41db..5cd464d9 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -12533,7 +12533,7 @@ check_one_cipher (int algo, int mode, int flags) 0, 61)) goto out; } - else if (mode == GCRY_CIPHER_MODE_CTR) + else if (mode == GCRY_CIPHER_MODE_CTR) { /* 32bit overflow test (big-endian counter) */ if (check_one_cipher_ctr_overflow (algo, mode, flags, key, 64, plain, @@ -17215,7 +17215,7 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, " (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#)\n" " (random-override #4253647587980912233445566778899019283747#))\n", GCRY_PK_RSA, - 0 }, + 0, FLAG_NOFIPS }, { "(data\n (flags pss)\n" " (hash-algo sha1)\n" " (value #11223344556677889900AA#))\n", @@ -17226,7 +17226,7 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, " (value #11223344556677889900AA#)\n" " (random-override #4253647587980912233445566778899019283747#))\n", GCRY_PK_RSA, - 0 }, + 0, FLAG_NOFIPS}, { "(data\n (flags pss)\n" " (hash-algo sha256)\n" " (value #11223344556677889900AABBCCDDEEFF#)\n" @@ -17234,7 +17234,7 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, " (random-override #42536475879809122334455667788990192837465564738291" "00122334455667#))\n", GCRY_PK_RSA, - 0 }, + 0, FLAG_NOFIPS }, { "(data\n (flags pss)\n" " (hash-algo sha256)\n" " (value #11223344556677889900AABBCCDDEEFF#)\n" @@ -17273,7 +17273,11 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, goto next; } if (gcry_err_code (rc) != datas[dataidx].expected_rc) - fail ("gcry_pk_sign %d failed: %s\n", dataidx, gpg_strerror (rc)); + { + show_sexp("hash: ", hash); + show_sexp("skey: ", skey); + fail ("gcry_pk_sign %d failed: %s\n", dataidx, gpg_strerror (rc)); + } if (!rc) verify_one_signature (pkey, hash, badhash, sig); @@ -17402,7 +17406,7 @@ check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey, goto next; } if (gcry_err_code (rc) != datas[dataidx].expected_rc) - fail ("gcry_pk_sign failed: %s\n", gpg_strerror (rc)); + fail ("gcry_pk_sign (%d) failed: %s\n", dataidx, gpg_strerror (rc)); if (!rc && verbose > 1) show_sexp ("ECDSA signature:\n", sig); @@ -17483,7 +17487,7 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, "(flags oaep)(hash-algo sha1)(label \"test\")", 1, 0, - 0 }, + 0, FLAG_NOFIPS }, { 0, "(data\n (flags )\n" " (value #11223344556677889900AA#))\n", NULL, @@ -17556,14 +17560,18 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, die ("converting data failed: %s\n", gpg_strerror (rc)); rc = gcry_pk_encrypt (&ciph, data, pkey); - if (in_fips_mode && (flags & FLAG_NOFIPS)) + if (in_fips_mode && (flags & FLAG_NOFIPS || datas[dataidx].flags & FLAG_NOFIPS)) { if (!rc) fail ("gcry_pk_encrypt did not fail as expected in FIPS mode\n"); goto next; } if (gcry_err_code (rc) != datas[dataidx].encrypt_expected_rc) - fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (rc)); + { + show_sexp("data: ", data); + show_sexp("pkey: ", pkey); + fail ("gcry_pk_encrypt (%d) failed: %s\n", flags, gpg_strerror (rc)); + } if (!rc) { @@ -17605,16 +17613,17 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, ciph = list; } rc = gcry_pk_decrypt (&plain, ciph, skey); - if (!rc && (datas[dataidx].flags & FLAG_SPECIAL)) - { - /* It may happen that OAEP formatted data which is - decrypted as pkcs#1 data returns a valid pkcs#1 - frame. However, the returned value will not be - identical - thus we expect a mismatch and test further on - whether this mismatch actually happened. */ - expect_mismatch = 1; - } - else if (gcry_err_code (rc) != datas[dataidx].decrypt_expected_rc) + + if (!rc && (datas[dataidx].flags & FLAG_SPECIAL)) + { + /* It may happen that OAEP formatted data which is + decrypted as pkcs#1 data returns a valid pkcs#1 + frame. However, the returned value will not be + identical - thus we expect a mismatch and test further on + whether this mismatch actually happened. */ + expect_mismatch = 1; + } + else if (gcry_err_code (rc) != datas[dataidx].decrypt_expected_rc) { if (verbose) { diff --git a/tests/pkcs1v2.c b/tests/pkcs1v2.c index 9874b81c..25156d65 100644 --- a/tests/pkcs1v2.c +++ b/tests/pkcs1v2.c @@ -186,8 +186,15 @@ check_oaep (void) err = gcry_pk_encrypt (&ciph, plain, pub_key); if (err) { - show_sexp ("plain:\n", ciph); - fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err)); + /* SKIP the test in fips mode, random-override is not allowed */ + if (in_fips_mode && gcry_err_code (err) == GPG_ERR_INV_FLAG) + { + gcry_sexp_release (plain); + continue; + } + show_sexp ("plain:\n", plain); + show_sexp ("pub_key:\n", pub_key); + fail ("gcry_pk_encrypt failed: (%d) %s\n", mno, gpg_strerror (err)); } else { @@ -320,6 +327,11 @@ check_pss (void) err = gcry_pk_sign (&sig, sigtmpl, sec_key); if (err) { + if (in_fips_mode && gcry_err_code (err) == GPG_ERR_INV_FLAG) + { + gcry_sexp_release (sigtmpl); + continue; + } show_sexp ("sigtmpl:\n", sigtmpl); fail ("gcry_pk_sign failed: %s\n", gpg_strerror (err)); } @@ -448,7 +460,12 @@ check_v15crypt (void) err = gcry_pk_encrypt (&ciph, plain, pub_key); if (err) { - show_sexp ("plain:\n", ciph); + if (in_fips_mode && gcry_err_code (err) == GPG_ERR_INV_FLAG) + { + gcry_sexp_release (plain); + continue; + } + show_sexp ("plain:\n", plain); fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err)); } else diff --git a/tests/t-dsa.c b/tests/t-dsa.c index 8ed3b65b..3f8ad97e 100644 --- a/tests/t-dsa.c +++ b/tests/t-dsa.c @@ -322,6 +322,10 @@ one_test_sexp (const char *sha_alg, err = gcry_pk_random_override_new (&ctx, buffer2, buflen2); if (err) { + /* Setting rsa salt is not allowed in FIPS mode */ + if (in_fips_mode && gpg_err_code (err) == GPG_ERR_INV_OP) + goto leave; + fail ("error setting salt for test: %s", gpg_strerror (err)); goto leave; diff --git a/tests/t-ecdsa.c b/tests/t-ecdsa.c index d36d217b..73f283ac 100644 --- a/tests/t-ecdsa.c +++ b/tests/t-ecdsa.c @@ -357,6 +357,10 @@ one_test_sexp (const char *curvename, const char *sha_alg, err = gcry_pk_random_override_new (&ctx, buffer2, buflen2); if (err) { + /* Setting salt is not allowed in FIPS mode */ + if (in_fips_mode && gpg_err_code (err) == GPG_ERR_INV_OP) + goto leave; + fail ("error setting salt for test: %s", gpg_strerror (err)); goto leave; diff --git a/tests/t-ed25519.c b/tests/t-ed25519.c index ce828b27..3b78c365 100644 --- a/tests/t-ed25519.c +++ b/tests/t-ed25519.c @@ -265,6 +265,10 @@ one_test (int testno, const char *sk, const char *pk, err = gcry_pk_input_data_push (&ctx, buffer, buflen); if (err) { + /* Setting salt is not allowed in FIPS mode */ + if (!no_fips && gpg_err_code (err) == GPG_ERR_INV_OP) + goto leave; + fail ("error setting input data for test: %s", gpg_strerror (err)); goto leave; diff --git a/tests/t-ed448.c b/tests/t-ed448.c index b68fd855..0761c9a0 100644 --- a/tests/t-ed448.c +++ b/tests/t-ed448.c @@ -37,6 +37,7 @@ static int sign_with_pk; static int no_verify; static int custom_data_file; +static int in_fips_mode; static void show_note (const char *format, ...) @@ -261,6 +262,9 @@ one_test (int testno, int ph, const char *sk, const char *pk, err = gcry_pk_input_data_push (&ctx, buffer, buflen); if (err) { + /* Setting salt is not allowed in FIPS mode */ + if (in_fips_mode && gpg_err_code (err) == GPG_ERR_INV_OP) + goto leave; fail ("error setting input data for test: %s", gpg_strerror (err)); goto leave; @@ -517,6 +521,9 @@ main (int argc, char **argv) xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + if (gcry_fips_mode_active ()) + in_fips_mode = 1; + start_timer (); check_ed448 (fname); stop_timer (); diff --git a/tests/t-fips-service-ind.c b/tests/t-fips-service-ind.c index f8485176..95807783 100644 --- a/tests/t-fips-service-ind.c +++ b/tests/t-fips-service-ind.c @@ -47,6 +47,9 @@ check_pk_g_t_n_c (int reject) static struct { const char *keyparms; int expect_failure; + int expect_failure_testkey; + int expect_failure_nbits; + int expect_failure_curve; } tv[] = { { "(genkey (ecc (curve nistp256)))", @@ -54,8 +57,12 @@ check_pk_g_t_n_c (int reject) }, { /* non-compliant curve */ "(genkey (ecc (curve secp256k1)))", - 1 - } + 1, 1, 1, 1 + }, + { /* non-compliant igninvflag */ + "(genkey (ecc (curve nistp256) (flags igninvflag)))", + 1, 0, 0, 0 + }, }; int tvidx; gpg_error_t err; @@ -138,14 +145,14 @@ check_pk_g_t_n_c (int reject) goto next; } - if (in_fips_mode && !tv[tvidx].expect_failure && ec) + if (in_fips_mode && !tv[tvidx].expect_failure_testkey && ec) { /* Success with the FIPS service indicator == 0 expected, but != 0. */ fail ("gcry_pk_testkey test %d unexpectedly set the indicator in FIPS mode.\n", tvidx); goto next; } - else if (in_fips_mode && tv[tvidx].expect_failure && !ec) + else if (in_fips_mode && tv[tvidx].expect_failure_testkey && !ec) { /* Success with the FIPS service indicator != 0 expected, but == 0. */ fail ("gcry_pk_testkey test %d unexpectedly cleared the indicator in FIPS mode.\n", @@ -169,14 +176,14 @@ check_pk_g_t_n_c (int reject) goto next; } - if (in_fips_mode && !tv[tvidx].expect_failure && ec) + if (in_fips_mode && !tv[tvidx].expect_failure_nbits && ec) { /* Success with the FIPS service indicator == 0 expected, but != 0. */ fail ("gcry_pk_get_nbits test %d unexpectedly set the indicator in FIPS mode.\n", tvidx); goto next; } - else if (in_fips_mode && tv[tvidx].expect_failure && !ec) + else if (in_fips_mode && tv[tvidx].expect_failure_nbits && !ec) { /* Success with the FIPS service indicator != 0 expected, but == 0. */ fail ("gcry_pk_get_nbits test %d unexpectedly cleared the indicator in FIPS mode.\n", @@ -200,14 +207,14 @@ check_pk_g_t_n_c (int reject) goto next; } - if (in_fips_mode && !tv[tvidx].expect_failure && ec) + if (in_fips_mode && !tv[tvidx].expect_failure_curve && ec) { /* Success with the FIPS service indicator == 0 expected, but != 0. */ fail ("gcry_pk_get_curve test %d unexpectedly set the indicator in FIPS mode.\n", tvidx); goto next; } - else if (in_fips_mode && tv[tvidx].expect_failure && !ec) + else if (in_fips_mode && tv[tvidx].expect_failure_curve && !ec) { /* Success with the FIPS service indicator != 0 expected, but == 0. */ fail ("gcry_pk_get_curve test %d unexpectedly cleared the indicator in FIPS mode.\n", @@ -404,6 +411,7 @@ check_pk_hash_sign_verify (void) const char *k; int expect_failure; int expect_failure_hash; + int expect_failure_verify; } tv[] = { { /* non-compliant hash */ GCRY_MD_BLAKE2B_512, @@ -414,18 +422,28 @@ check_pk_hash_sign_verify (void) "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))", "(data(flags raw)(hash %s %b)(label %b))", "94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de", - 1, 1 + 1, 1, 1 }, { /* non-compliant curve */ GCRY_MD_SHA256, "(private-key (ecc (curve secp256k1)" " (d #c2cdf0a8b0a83b35ace53f097b5e6e6a0a1f2d40535eff1cf434f52a43d59d8f#)))", - "(public-key (ecc (curve secp256k1)" " (q #046fcc37ea5e9e09fec6c83e5fbd7a745e3eee81d16ebd861c9e66f55518c19798" "4e9f113c07f875691df8afc1029496fc4cb9509b39dcd38f251a83359cc8b4f7#)))", "(data(flags raw)(hash %s %b)(label %b))", "94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de", + 1, 0, 1 + }, + { /* non-compliant igninvflag */ + GCRY_MD_SHA256, + "(private-key (ecc (curve nistp256) (flags igninvflag)" + " (d #519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464#)))", + "(public-key (ecc (curve nistp256)" + " (q #041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83" + "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))", + "(data(flags raw)(hash %s %b)(label %b))", + "94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de", 1, 0 }, { @@ -438,6 +456,17 @@ check_pk_hash_sign_verify (void) "(data(flags raw)(hash %s %b)(label %b))", "94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de", 0, 0 + }, + { + GCRY_MD_GOSTR3411_94, /* non-compliant hash */ + "(private-key (ecc (curve nistp256)" + " (d #519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464#)))", + "(public-key (ecc (curve nistp256)" + " (q #041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83" + "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))", + "(data(flags raw)(hash %s %b)(label %b))", + "94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de", + 1, 1, 1 } }; int tvidx; @@ -573,14 +602,14 @@ check_pk_hash_sign_verify (void) goto next; } - if (in_fips_mode && !tv[tvidx].expect_failure && ec) + if (in_fips_mode && !tv[tvidx].expect_failure_verify && ec) { /* Success with the FIPS service indicator == 0 expected, but != 0. */ fail ("gcry_pk_hash test %d unexpectedly set the indicator in FIPS mode.\n", tvidx); goto next; } - else if (in_fips_mode && tv[tvidx].expect_failure && !ec) + else if (in_fips_mode && tv[tvidx].expect_failure_verify && !ec) { /* Success with the FIPS service indicator != 0 expected, but == 0. */ fail ("gcry_pk_hash_verify test %d unexpectedly cleared the indicator in FIPS mode.\n", diff --git a/tests/t-rsa-pss.c b/tests/t-rsa-pss.c index 82dd54b3..2206c291 100644 --- a/tests/t-rsa-pss.c +++ b/tests/t-rsa-pss.c @@ -283,6 +283,10 @@ one_test_sexp (const char *n, const char *e, const char *d, err = gcry_pk_random_override_new (&ctx, buffer2, buflen2); if (err) { + /* Setting rsa salt is not allowed in FIPS mode */ + if (in_fips_mode && gpg_err_code (err) == GPG_ERR_INV_OP) + goto leave; + fail ("error setting salt for test: %s", gpg_strerror (err)); goto leave; -- 2.48.1 From lucas.mulling at suse.com Wed Feb 26 21:19:24 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Wed, 26 Feb 2025 17:19:24 -0300 Subject: [PATCH 3/4] cipher, visibility: Differentiate use of random-override in the SLI In-Reply-To: <20250226202131.381279-1-lucas.mulling@suse.com> References: <20250226202131.381279-1-lucas.mulling@suse.com> Message-ID: <20250226202131.381279-4-lucas.mulling@suse.com> * cipher/pubkey-util.c (_gcry_pk_util_data_to_mpi, _gcry_pk_single_data_push, _gcry_pk_util_free_encoding_ctx): Differentiate use of random-override in the SLI. * src/visibility.c (gcry_pk_random_override_new): Differentiate use explicit random override in the SLI. Signed-off-by: Lucas Mulling --- cipher/pubkey-util.c | 37 ++++++++++++++++++++++++++++++++++++- src/visibility.c | 13 +++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index 9c927638..ac2cde76 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -662,7 +662,6 @@ _gcry_pk_util_free_encoding_ctx (struct pk_encoding_ctx *ctx) xfree (ctx->label); } - /* Take the hash value and convert into an MPI, suitable for passing to the low level functions. We currently support the old style way of passing just a MPI and the modern interface which @@ -973,6 +972,18 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, list = sexp_find_token (ldata, "random-override", 0); if (list) { + if(fips_mode ()) + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK)) + { + sexp_release (list); + rc = GPG_ERR_INV_FLAG; + goto leave; + } + else + fips_service_indicator_mark_non_compliant (); + + } s = sexp_nth_data (list, 1, &n); if (!s) rc = GPG_ERR_NO_OBJ; @@ -1149,6 +1160,18 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, list = sexp_find_token (ldata, "random-override", 0); if (list) { + if(fips_mode ()) + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK)) + { + sexp_release (list); + rc = GPG_ERR_INV_FLAG; + goto leave; + } + else + fips_service_indicator_mark_non_compliant (); + + } s = sexp_nth_data (list, 1, &n); if (!s) rc = GPG_ERR_NO_OBJ; @@ -1248,6 +1271,18 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, list = sexp_find_token (ldata, "random-override", 0); if (list) { + if(fips_mode ()) + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK)) + { + sexp_release (list); + rc = GPG_ERR_INV_FLAG; + goto leave; + } + else + fips_service_indicator_mark_non_compliant (); + + } s = sexp_nth_data (list, 1, &n); if (!s) rc = GPG_ERR_NO_OBJ; diff --git a/src/visibility.c b/src/visibility.c index e02d6cfe..14b8fa25 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -1085,6 +1085,19 @@ gcry_pk_hash_verify (gcry_sexp_t sigval, const char *data_tmpl, gcry_sexp_t pkey gcry_error_t gcry_pk_random_override_new (gcry_ctx_t *r_ctx, const unsigned char *p, size_t len) { + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + fips_service_indicator_init (); + + if(fips_mode ()) + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK)) + return GPG_ERR_INV_OP; + else + fips_service_indicator_mark_non_compliant (); + + } + return gpg_error (_gcry_pk_single_data_push (r_ctx, p, len)); } -- 2.48.1 From lucas.mulling at suse.com Wed Feb 26 21:19:23 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Wed, 26 Feb 2025 17:19:23 -0300 Subject: [PATCH 2/4] cipher: Differentiate no-blinding flag in the SLI In-Reply-To: <20250226202131.381279-1-lucas.mulling@suse.com> References: <20250226202131.381279-1-lucas.mulling@suse.com> Message-ID: <20250226202131.381279-3-lucas.mulling@suse.com> * cipher/rsa.c (rsa_decrypt, rsa_encrypt): Differentiate use of flag no-blinding in the service level indicator. Signed-off-by: Lucas Mulling --- cipher/rsa.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/cipher/rsa.c b/cipher/rsa.c index c7a809f4..bee40b37 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -1501,7 +1501,19 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) be practically mounted over the network as shown by Brumley and Boney in 2003. */ if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING)) - secret (plain, data, &sk); + { + if (fips_mode ()) + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK)) + { + rc = GPG_ERR_INV_FLAG; + goto leave; + } + else + fips_service_indicator_mark_non_compliant (); + } + secret (plain, data, &sk); + } else secret_blinded (plain, data, &sk, nbits); @@ -1615,8 +1627,22 @@ rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) /* Do RSA computation. */ sig = mpi_new (0); + if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING)) - secret (sig, data, &sk); + { + if (fips_mode ()) + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK)) + { + rc = GPG_ERR_INV_FLAG; + goto leave; + } + else + fips_service_indicator_mark_non_compliant (); + } + + secret (sig, data, &sk); + } else secret_blinded (sig, data, &sk, nbits); if (DBG_CIPHER) -- 2.48.1 From lucas.mulling at suse.com Wed Feb 26 21:19:22 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Wed, 26 Feb 2025 17:19:22 -0300 Subject: [PATCH 1/4] cipher: Differentiate igninvflag in the SLI In-Reply-To: <20250226202131.381279-1-lucas.mulling@suse.com> References: <20250226202131.381279-1-lucas.mulling@suse.com> Message-ID: <20250226202131.381279-2-lucas.mulling@suse.com> * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Differentiate use of igninvflag. Signed-off-by: Lucas Mulling --- cipher/pubkey-util.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index 68defea6..9c927638 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -200,6 +200,14 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, } } + if (fips_mode () && igninvflag) + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK)) + rc = GPG_ERR_INV_FLAG; + else + fips_service_indicator_mark_non_compliant (); + } + if (r_flags) *r_flags = flags; if (r_encoding) -- 2.48.1 From lucas.mulling at suse.com Thu Feb 27 21:09:13 2025 From: lucas.mulling at suse.com (Lucas Mulling) Date: Thu, 27 Feb 2025 17:09:13 -0300 Subject: T7338: Make SHA1 non-FIPS and differentiate in the SLI In-Reply-To: <87wmdd1d36.fsf@haruna.fsij.org> References: <8734gjfu2k.fsf@jacob.g10code.de> <875xldeqz4.fsf@jacob.g10code.de> <87ikpdqt7h.fsf@haruna.fsij.org> <87cyfeznz5.fsf@haruna.fsij.org> <87msehks8y.fsf@haruna.fsij.org> <877c5jyi0c.fsf@haruna.fsij.org> <87jz9eh3fm.fsf@haruna.fsij.org> <871pvl2s94.fsf@haruna.fsij.org> <87wmdd1d36.fsf@haruna.fsij.org> Message-ID: Hello, Sorry for the delay, I've tested the patches everything seems to be in order. The only thing I had to change was: diff --git a/tests/basic.c b/tests/basic.c index f32e41db..5e1f94b5 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -17268,8 +17268,9 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, rc = gcry_pk_sign (&sig, hash, skey); if (in_fips_mode && (flags & FLAG_NOFIPS || datas[dataidx].flags & FLAG_NOFIPS)) { - if (!rc) - fail ("gcry_pk_sign did not fail as expected in FIPS mode\n"); + if ((datas[dataidx].expected_rc && !rc)) + fail ("gcry_pk_sign (%d) did not fail as expected in FIPS mode\n", + dataidx); goto next; } if (gcry_err_code (rc) != datas[dataidx].expected_rc) Or maybe GCRY_FIPS_FLAG_REJECT_PK_MD should be enabled by default?