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.
-- 
>From 6970e93a7f45e0bd2d553239555f03e7ec3e25fa Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gni...@fsij.org>
Date: Mon, 10 Feb 2025 13:32:55 +0900
Subject: [PATCH 1/3] cipher:(EC)DSA: Fix _gcry_dsa_modify_k to least leak.

* cipher/dsa-common.c (_gcry_dsa_modify_k): Use _gcry_mpih_add_lli.

--

GnuPG-bug-id: 7519
Signed-off-by: NIIBE Yutaka <gni...@fsij.org>
---
 cipher/dsa-common.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/cipher/dsa-common.c b/cipher/dsa-common.c
index 170dce12..8b401e78 100644
--- a/cipher/dsa-common.c
+++ b/cipher/dsa-common.c
@@ -25,6 +25,7 @@
 
 #include "g10lib.h"
 #include "mpi.h"
+#include "mpi-internal.h"
 #include "cipher.h"
 #include "pubkey-internal.h"
 
@@ -42,15 +43,21 @@
 void
 _gcry_dsa_modify_k (gcry_mpi_t k, gcry_mpi_t q, int qbits)
 {
-  gcry_mpi_t k1 = mpi_new (qbits+2);
-
-  mpi_resize (k, (qbits+2+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB);
-  k->nlimbs = k->alloced;
-  mpi_add (k, k, q);
-  mpi_add (k1, k, q);
-  mpi_set_cond (k, k1, (1 - mpi_test_bit (k, qbits)));
-
-  mpi_free (k1);
+  mpi_limb_t cy;
+  unsigned long once_more;
+  mpi_size_t ksize;
+
+  ksize = (qbits+1+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB;
+  mpi_resize (k, ksize);
+  k->nlimbs = ksize;
+
+  cy = _gcry_mpih_add_lli (k->d, k->d, q->d, q->nlimbs);
+  if (k->nlimbs > q->nlimbs)
+      k->d[k->nlimbs-1] = cy;
+  once_more = 1 - mpi_test_bit (k, qbits);
+  _gcry_mpih_add_n_cond (k->d, k->d, q->d, q->nlimbs, once_more);
+  if (k->nlimbs > q->nlimbs)
+      k->d[k->nlimbs-1] = 1;
 }
 
 /*
-- 
2.39.5

>From 27cf880c80f7390e506bab0d8e0b43cb31cfe833 Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gni...@fsij.org>
Date: Mon, 17 Feb 2025 14:15:17 +0900
Subject: [PATCH 2/3] cipher:(EC)DSA: Avoid MPI normalize by mpi_rshift.

* cipher/dsa-common.c (_gcry_dsa_gen_rfc6979_k): Use
_gcry_mpi_set_buffer and _gcry_mpih_rshift, instead of _gcry_mpi_scan
and mpi_rshift.

--

GnuPG-bug-id: 7519
Signed-off-by: NIIBE Yutaka <gni...@fsij.org>
---
 cipher/dsa-common.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/cipher/dsa-common.c b/cipher/dsa-common.c
index 8b401e78..0d8d121f 100644
--- a/cipher/dsa-common.c
+++ b/cipher/dsa-common.c
@@ -320,12 +320,14 @@ _gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
 
   /* k = bits2int (T) */
   mpi_free (k);
-  k = NULL;
-  rc = _gcry_mpi_scan (&k, GCRYMPI_FMT_USG, t, (tbits+7)/8, NULL);
-  if (rc)
-    goto leave;
-  if (tbits > qbits)
-    mpi_rshift (k, k, tbits - qbits);
+  k = mpi_alloc_secure ((qbits+7)/8);
+  _gcry_mpi_set_buffer (k, t, (qbits+7)/8, 0);
+  if (qbits % 8)
+    {
+      unsigned int nbits = 8 - (qbits % 8);
+
+      _gcry_mpih_rshift (k->d, k->d, k->nlimbs, nbits);
+    }
 
   /* Check: k < q and k > 1 */
   if (!(mpi_cmp (k, dsa_q) < 0 && mpi_cmp_ui (k, 0) > 0))
-- 
2.39.5

>From a4f435e0920a0280465d0dceeac13e3624cabb8b Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gni...@fsij.org>
Date: Mon, 17 Feb 2025 14:18:38 +0900
Subject: [PATCH 3/3] cipher:(EC)DSA: Fix _gcry_dsa_gen_*k not to normalize
 MPI.

* cipher/dsa-common.c (_gcry_dsa_gen_k): Use _gcry_mpih_cmp_lli
and _gcry_mpih_cmp_ui.
(_gcry_dsa_gen_rfc6979_k): Likewise.

--

GnuPG-bug-id: 7519
Signed-off-by: NIIBE Yutaka <gni...@fsij.org>
---
 cipher/dsa-common.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/cipher/dsa-common.c b/cipher/dsa-common.c
index 0d8d121f..d63defda 100644
--- a/cipher/dsa-common.c
+++ b/cipher/dsa-common.c
@@ -112,13 +112,13 @@ _gcry_dsa_gen_k (gcry_mpi_t q, int security_level)
           mpi_clear_bit (k, nbits-1);
 	}
 
-      if (!(mpi_cmp (k, q) < 0))    /* check: k < q */
+      if (!(_gcry_mpih_cmp_lli (k->d, q->d, k->nlimbs) < 0))    /* check: k < q */
         {
           if (DBG_CIPHER)
             log_debug ("\tk too large - again\n");
           continue; /* no  */
         }
-      if (!(mpi_cmp_ui (k, 0) > 0)) /* check: k > 0 */
+      if (!(_gcry_mpih_cmp_ui (k->d, k->nlimbs, 0) > 0)) /* check: k > 0 */
         {
           if (DBG_CIPHER)
             log_debug ("\tk is zero - again\n");
@@ -330,7 +330,8 @@ _gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
     }
 
   /* Check: k < q and k > 1 */
-  if (!(mpi_cmp (k, dsa_q) < 0 && mpi_cmp_ui (k, 0) > 0))
+  if (!(_gcry_mpih_cmp_lli (k->d, dsa_q->d, k->nlimbs) < 0
+        && _gcry_mpih_cmp_ui (k->d, k->nlimbs, 0) > 0))
     {
       /* K = HMAC_K(V || 0x00) */
       rc = _gcry_md_setkey (hd, K, hlen);
-- 
2.39.5

_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel

Reply via email to