[PATCH 07/10] mceliece6688128f: harden mask generation against branch optimization

Jussi Kivilinna jussi.kivilinna at iki.fi
Sat Sep 27 09:54:16 CEST 2025


* cipher/mceliece6688128f.c (crypto_int64_negative_mask)
(crypto_int16_negative_mask, crypto_int32_negative_mask)
(crypto_uint64_signed_negative_mask, crypto_uint16_signed_negative_mask)
(crypto_uint32_signed_negative_mask, mask_nonzero, mask_leq, vec_cmov)
(layer, gen_e, gf_mul, same_mask, pk_gen): Generate masks with
const-time helper function.
* src/const-time.h (ct_u64_gen_mask, ct_u64_gen_inv_mask): New.
--

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 cipher/mceliece6688128f.c | 34 +++++++++++++++++-----------------
 src/const-time.h          |  3 +++
 2 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c
index bdc7f265..4c4eb0bd 100644
--- a/cipher/mceliece6688128f.c
+++ b/cipher/mceliece6688128f.c
@@ -132,6 +132,7 @@
 
 #include "g10lib.h"
 #include "bufhelp.h"
+#include "const-time.h"
 #include "mceliece6688128f.h"
 
 static void
@@ -195,7 +196,7 @@ static void crypto_declassify(void *crypto_declassify_v,long long crypto_declass
 GCC_ATTR_UNUSED
 static crypto_int64 crypto_int64_negative_mask(crypto_int64 crypto_int64_x)
 {
-  return crypto_int64_x >> (64-1);
+  return ct_u64_gen_mask((u64)crypto_int64_x >> (64-1));
 }
 
 GCC_ATTR_UNUSED
@@ -287,7 +288,7 @@ static void crypto_int64_minmax(crypto_int64 *crypto_int64_a,crypto_int64 *crypt
 GCC_ATTR_UNUSED
 static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x)
 {
-  return crypto_int16_x >> (16-1);
+  return ct_ulong_gen_mask((u16)crypto_int16_x >> (16-1));
 }
 
 GCC_ATTR_UNUSED
@@ -379,7 +380,7 @@ static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypt
 GCC_ATTR_UNUSED
 static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x)
 {
-  return crypto_int32_x >> (32-1);
+  return ct_ulong_gen_mask((u32)crypto_int32_x >> (32-1));
 }
 
 GCC_ATTR_UNUSED
@@ -472,7 +473,7 @@ static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypt
 GCC_ATTR_UNUSED
 static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x)
 {
-  return crypto_uint64_signed_x >> (64-1);
+  return ct_u64_gen_mask((u64)crypto_uint64_signed_x >> (64-1));
 }
 
 GCC_ATTR_UNUSED
@@ -557,7 +558,7 @@ static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *c
 GCC_ATTR_UNUSED
 static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x)
 {
-  return crypto_uint16_signed_x >> (16-1);
+  return ct_ulong_gen_mask((crypto_uint16)crypto_uint16_signed_x >> (16-1));
 }
 
 GCC_ATTR_UNUSED
@@ -642,7 +643,7 @@ static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *c
 GCC_ATTR_UNUSED
 static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x)
 {
-  return crypto_uint32_signed_x >> (32-1);
+  return ct_ulong_gen_mask((crypto_uint32)crypto_uint32_signed_x >> (32-1));
 }
 
 GCC_ATTR_UNUSED
@@ -1484,7 +1485,7 @@ static inline uint16_t mask_nonzero(gf a)
 
 	ret -= 1;
 	ret >>= 31;
-	ret -= 1;
+	ret = ct_ulong_gen_inv_mask(ret);
 
 	return ret;
 }
@@ -1496,7 +1497,7 @@ static inline uint16_t mask_leq(uint16_t a, uint16_t b)
 	uint32_t ret = b_tmp - a_tmp;
 
 	ret >>= 31;
-	ret -= 1;
+	ret = ct_ulong_gen_inv_mask(ret);
 
 	return ret;
 }
@@ -1508,7 +1509,7 @@ static inline void vec_cmov(vec * out, vec * in, uint16_t mask)
 	vec m0, m1;
 
 	m0 = vec_set1_16b(mask);
-	m1 = ~m0;
+	m1 = vec_set1_16b((uint16_t)ct_ulong_gen_inv_mask(mask & 1));
 
 	for (i = 0; i < GFBITS; i++)
 	{
@@ -1884,8 +1885,7 @@ static void layer(int16_t *p, const unsigned char *cb, int s, int n)
     for (j = 0; j < stride; j++)
     {
       d = p[ i+j ] ^ p[ i+j+stride ];
-      m = (cb[ index >> 3 ] >> (index & 7)) & 1;
-      m = -m;
+      m = ct_ulong_gen_mask((cb[ index >> 3 ] >> (index & 7)) & 1);
       d &= m;
       p[ i+j ] ^= d;
       p[ i+j+stride ] ^= d;
@@ -2224,7 +2224,7 @@ static void gen_e(unsigned char *e)
 			mask = i ^ (ind[j] >> 6);
 			mask -= 1;
 			mask >>= 63;
-			mask = -mask;
+			mask = ct_u64_gen_mask(mask);
 
 			e_int[i] |= val[j] & mask;
 		}
@@ -2799,7 +2799,7 @@ gf gf_mul(gf in0, gf in1)
 	t0 = in0;
 	t1 = in1;
 
-	tmp = t0 * (t1 & 1);
+	tmp = t0 & ct_u64_gen_mask(t1 & 1);
 
 	for (i = 1; i < GFBITS; i++)
 		tmp ^= (t0 * (t1 & (1 << i)));
@@ -3241,7 +3241,7 @@ static inline uint64_t same_mask(uint16_t x, uint16_t y)
         mask = x ^ y;
         mask -= 1;
         mask >>= 63;
-        mask = -mask;
+        mask = ct_u64_gen_mask(mask);
 
         return mask;
 }
@@ -3408,7 +3408,7 @@ static int pk_gen_mat(unsigned char * pk, const unsigned char * irr, uint32_t *
 		{
 			mask = mat[ row ][ i ] >> j;
 			mask &= 1;
-			mask -= 1;
+			mask = ct_u64_gen_inv_mask(mask);
 
 			for (c = 0; c < nblocks_H; c++)
 				mat[ row ][ c ] ^= mat[ k ][ c ] & mask;
@@ -3423,7 +3423,7 @@ static int pk_gen_mat(unsigned char * pk, const unsigned char * irr, uint32_t *
 		{
 			mask = mat[ k ][ i ] >> j;
 			mask &= 1;
-			mask = -mask;
+			mask = ct_u64_gen_mask(mask);
 
 			for (c = 0; c < nblocks_H; c++)
 				mat[ k ][ c ] ^= mat[ row ][ c ] & mask;
@@ -3433,7 +3433,7 @@ static int pk_gen_mat(unsigned char * pk, const unsigned char * irr, uint32_t *
 		{
 			mask = mat[ k ][ i ] >> j;
 			mask &= 1;
-			mask = -mask;
+			mask = ct_u64_gen_mask(mask);
 
 			for (c = 0; c < nblocks_H; c++)
 				mat[ k ][ c ] ^= mat[ row ][ c ] & mask;
diff --git a/src/const-time.h b/src/const-time.h
index c2acbb73..03a47d65 100644
--- a/src/const-time.h
+++ b/src/const-time.h
@@ -114,6 +114,7 @@ unsigned int _gcry_ct_memequal (const void *b1, const void *b2, size_t len);
 DEFINE_CT_TYPE_GEN_MASK(uintptr, uintptr_t)
 DEFINE_CT_TYPE_GEN_MASK(ulong, unsigned long)
 DEFINE_CT_TYPE_GEN_MASK(int16, int16_t)
+DEFINE_CT_TYPE_GEN_MASK(u64, u64)
 
 /*
  * Return all bits set if A is 0 and return 1 otherwise.
@@ -139,6 +140,7 @@ DEFINE_CT_TYPE_GEN_MASK(int16, int16_t)
 DEFINE_CT_TYPE_GEN_INV_MASK(uintptr, uintptr_t)
 DEFINE_CT_TYPE_GEN_INV_MASK(ulong, unsigned long)
 DEFINE_CT_TYPE_GEN_INV_MASK(int16, int16_t)
+DEFINE_CT_TYPE_GEN_INV_MASK(u64, u64)
 
 /*
  *  Return A when OP_ENABLED=1
@@ -155,6 +157,7 @@ DEFINE_CT_TYPE_GEN_INV_MASK(int16, int16_t)
 DEFINE_CT_TYPE_SELECT_FUNC(uintptr, uintptr_t)
 DEFINE_CT_TYPE_SELECT_FUNC(ulong, unsigned long)
 DEFINE_CT_TYPE_SELECT_FUNC(int16, int16_t)
+DEFINE_CT_TYPE_SELECT_FUNC(u64, u64)
 
 /*
  *  Return NULL when OP_ENABLED=1
-- 
2.48.1




More information about the Gcrypt-devel mailing list