]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
The timing resistant ecc_mulmod() is only used when signing using the ECDSA private...
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 8 Dec 2011 23:02:06 +0000 (00:02 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 8 Dec 2011 23:02:06 +0000 (00:02 +0100)
lib/nettle/Makefile.am
lib/nettle/ecc.h
lib/nettle/ecc_make_key.c
lib/nettle/ecc_mulmod.c
lib/nettle/ecc_mulmod_timing.c [new file with mode: 0644]
lib/nettle/ecc_sign_hash.c

index 24552dc94396a98cd61ff81b41a38e67193f42d7..e637bb1cb3b475468aed29c02f501a178b26d24c 100644 (file)
@@ -37,4 +37,4 @@ libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c init.c egd.c egd.h \
        multi.c ecc_free.c ecc.h ecc_make_key.c ecc_shared_secret.c \
        ecc_map.c ecc_mulmod.c ecc_points.c ecc_projective_dbl_point_3.c \
        ecc_projective_add_point.c ecc_projective_check_point.c \
-       ecc_sign_hash.c ecc_verify_hash.c gnettle.h
+       ecc_sign_hash.c ecc_verify_hash.c gnettle.h ecc_mulmod_timing.c
index d5a5fa013ef4f24a10e50d263cf027ec2fcbf962..7e0ed01fa43bcadfd492ca08a21430d136f58c3d 100644 (file)
@@ -84,7 +84,7 @@ void ecc_sizes(int *low, int *high);
 int  ecc_get_size(ecc_key *key);
 
 int ecc_make_key(void *random_ctx, nettle_random_func random, ecc_key *key, const ecc_set_type *dp);
-int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy);
+int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy, int timing_res);
 void ecc_free(ecc_key *key);
 
 int  ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, 
@@ -111,6 +111,7 @@ int ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mpz_t A,
 
 /* R = kG */
 int ecc_mulmod(mpz_t k, ecc_point *G, ecc_point *R, mpz_t a, mpz_t modulus, int map);
+int ecc_mulmod_timing(mpz_t k, ecc_point *G, ecc_point *R, mpz_t a, mpz_t modulus, int map);
 
 /* map P to affine from projective */
 int ecc_map(ecc_point *P, mpz_t modulus);
index 4972eabb309771a9fa98c47896dad1b48692aab4..34b6d637704fcbaa8e74507fbc8a2f15f58e0293 100644 (file)
   @param A            The "a" parameter of the curve
   @param Gx           The x coordinate of the base point
   @param Gy           The y coordinate of the base point
+  @timing_res         If non zero the function will try to return in constant time.
   @return 0 if successful, upon error all allocated memory will be freed
 */
 
 int
 ecc_make_key_ex (void *random_ctx, nettle_random_func random, ecc_key * key,
-                 mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy)
+                 mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy,
+                 int timing_res)
 {
   int err;
   ecc_point *base;
@@ -99,12 +101,14 @@ ecc_make_key_ex (void *random_ctx, nettle_random_func random, ecc_key * key,
       mpz_mod (key->k, key->k, key->order);
     }
   /* make the public key */
-  if ((err =
-       ecc_mulmod (key->k, base, &key->pubkey, key->A, key->prime,
-                       1)) != 0)
-    {
-      goto errkey;
-    }
+  if (timing_res)
+    err = ecc_mulmod_timing (key->k, base, &key->pubkey, key->A, key->prime, 1);
+  else
+    err = ecc_mulmod (key->k, base, &key->pubkey, key->A, key->prime, 1);
+
+  if (err != 0)
+    goto errkey;
+
   key->type = PK_PRIVATE;
 
   /* free up ram */
@@ -142,7 +146,7 @@ ecc_make_key (void *random_ctx, nettle_random_func random, ecc_key * key,
   mpz_set_str (A, (char *) dp->A, 16);
   mpz_set_str (B, (char *) dp->B, 16);
 
-  err = ecc_make_key_ex (random_ctx, random, key, prime, order, A, B, Gx, Gy);
+  err = ecc_make_key_ex (random_ctx, random, key, prime, order, A, B, Gx, Gy, 0);
 
   mp_clear_multi (&prime, &order, &A, &B, &Gx, &Gy, NULL);
 cleanup:
index 2f12759e9afec05d1a02a05a8906e01c10133013..2c1d46eb16d6572b8d66bdbe9ccef0535f53d0cf 100644 (file)
 
 #include "ecc.h"
 
-/*
-  @file ecc_mulmod_timing.c
-  ECC Crypto, Tom St Denis
-*/
+/* size of sliding window, don't change this! */
+#define WINSIZE 4
 
-/*
-   Perform a point multiplication  (timing resistant)
+/**
+   Perform a point multiplication 
    @param k    The scalar to multiply by
    @param G    The base point
    @param R    [out] Destination for kG
-   @param a        The a value of the curve
    @param modulus  The modulus of the field the ECC curve is in
    @param map      Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
-   @return 0 on success
+   @return CRYPT_OK on success
 */
 int
 ecc_mulmod (mpz_t k, ecc_point * G, ecc_point * R, mpz_t a, mpz_t modulus,
                 int map)
+
 {
-  ecc_point *tG, *M[3];
-  int i, j, err;
-  int bit_to_read;
-  int mode;
+   ecc_point *tG, *M[8];
+   int        i, j, err, bitidx;
+   int        first, bitbuf, bitcpy, bitcnt, mode;
 
-  if (k == NULL || G == NULL || R == NULL || modulus == NULL)
-    return -1;
+   if (k == NULL || G == NULL || R == NULL || modulus == NULL)
+     return -1;
 
   /* alloc ram for window temps */
-  for (i = 0; i < 3; i++)
-    {
-      M[i] = ecc_new_point ();
-      if (M[i] == NULL)
-        {
-          for (j = 0; j < i; j++)
-            {
-              ecc_del_point (M[j]);
-            }
-          return -1;
-        }
-    }
-
-  /* make a copy of G incase R==G */
-  tG = ecc_new_point ();
-  if (tG == NULL)
-    {
-      err = -1;
-      goto done;
-    }
-
-  /* tG = G  and convert to montgomery */
-  mpz_set (tG->x, G->x);
-  mpz_set (tG->y, G->y);
-  mpz_set (tG->z, G->z);
-
-  /* calc the M tab */
-  /* M[0] == G */
-  mpz_set (M[0]->x, tG->x);
-  mpz_set (M[0]->y, tG->y);
-  mpz_set (M[0]->z, tG->z);
-  /* M[1] == 2G */
-  if ((err = ecc_projective_dbl_point (tG, M[1], a, modulus)) != 0)
-    {
-      goto done;
-    }
-
-  /* setup sliding window */
-  mode = 0;
-  bit_to_read = mpz_size (k) * GMP_NUMB_BITS - 1;
-
-  /* perform ops */
-  for (;;)
-    {
-      /* grab next digit as required */
-      if (bit_to_read == -1)
-        break;
-      i = mpz_tstbit (k, bit_to_read--);
-      
-      if (mode == 0 && i == 0)
-        {
-          /* dummy operations */
-          if ((err =
-               ecc_projective_add_point (M[0], M[1], M[2], a,
-                                             modulus)) != 0)
-            {
-              goto done;
-            }
-          if ((err =
-               ecc_projective_dbl_point (M[1], M[2], a, modulus)) != 0)
-            {
-              goto done;
-            }
-          continue;
-        }
-
-      if (mode == 0 && i == 1)
-        {
-          mode = 1;
-          /* dummy operations */
-          if ((err =
-               ecc_projective_add_point (M[0], M[1], M[2], a,
-                                             modulus)) != 0)
-            {
-              goto done;
-            }
-          if ((err =
-               ecc_projective_dbl_point (M[1], M[2], a, modulus)) != 0)
-            {
-              goto done;
-            }
-          continue;
-        }
-
-      if ((err =
-           ecc_projective_add_point (M[0], M[1], M[i ^ 1], a,
-                                         modulus)) != 0)
-        {
+  for (i = 0; i < 8; i++) {
+      M[i] = ecc_new_point();
+      if (M[i] == NULL) {
+         for (j = 0; j < i; j++) {
+             ecc_del_point(M[j]);
+         }
+
+         return -1;
+      }
+  }
+
+   /* make a copy of G incase R==G */
+   tG = ecc_new_point();
+   if (tG == NULL)
+     { 
+       err = -1;
+       goto done; 
+     }
+
+   /* tG = G  and convert to montgomery */
+   mpz_set (tG->x, G->x);
+   mpz_set (tG->y, G->y);
+   mpz_set (tG->z, G->z);
+
+   /* calc the M tab, which holds kG for k==8..15 */
+   /* M[0] == 8G */
+   if ((err = ecc_projective_dbl_point (tG, M[0], a, modulus)) != 0)
+     goto done;
+
+   if ((err = ecc_projective_dbl_point (M[0], M[0], a, modulus)) != 0)
+     goto done;
+
+   if ((err = ecc_projective_dbl_point (M[0], M[0], a, modulus)) != 0)
+     goto done;
+   /* now find (8+k)G for k=1..7 */
+   for (j = 9; j < 16; j++) {
+     if (ecc_projective_add_point(M[j-9], tG, M[j-8], a, modulus) != 0)
+       goto done;
+   }
+
+   /* setup sliding window */
+   mode   = 0;
+   bitcnt = 1;
+   bitidx = mpz_size (k) * GMP_NUMB_BITS - 1;
+   bitcpy = bitbuf = 0;
+   first  = 1;
+
+   /* perform ops */
+   for (;;) {
+     /* grab next digit as required */
+     if (bitidx == -1) {
+       break;
+     }
+
+     /* grab the next msb from the ltiplicand */
+     i = mpz_tstbit (k, bitidx--);
+
+     /* skip leading zero bits */
+     if (mode == 0 && i == 0) {
+        continue;
+     }
+
+     /* if the bit is zero and mode == 1 then we double */
+     if (mode == 1 && i == 0) {
+        if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0)
           goto done;
-        }
-      if ((err = ecc_projective_dbl_point (M[i], M[i], a, modulus)) != 0)
-        {
-          goto done;
-        }
-    }
-
-  /* copy result out */
-  mpz_set (R->x, M[0]->x);
-  mpz_set (R->y, M[0]->y);
-  mpz_set (R->z, M[0]->z);
-
-  /* map R back from projective space */
-  if (map)
-    {
-      err = ecc_map (R, modulus);
+        continue;
+     }
+
+     /* else we add it to the window */
+     bitbuf |= (i << (WINSIZE - ++bitcpy));
+     mode = 2;
+
+     if (bitcpy == WINSIZE) {
+       /* if this is the first window we do a simple copy */
+       if (first == 1) {
+          /* R = kG [k = first window] */
+          mpz_set(R->x, M[bitbuf-8]->x);
+          mpz_set(R->y, M[bitbuf-8]->y);
+          mpz_set(R->z, M[bitbuf-8]->z);
+          first = 0;
+       } else {
+         /* normal window */
+         /* ok window is filled so double as required and add  */
+         /* double first */
+         for (j = 0; j < WINSIZE; j++) {
+           if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0)
+             goto done;
+         }
+
+         /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
+         if ((err = ecc_projective_add_point(R, M[bitbuf-8], R, a, modulus)) != 0)
+           goto done;
+       }
+       /* empty window and reset */
+       bitcpy = bitbuf = 0;
+       mode = 1;
     }
-  else
-    {
+  }
+
+   /* if bits remain then double/add */
+   if (mode == 2 && bitcpy > 0) {
+     /* double then add */
+     for (j = 0; j < bitcpy; j++) {
+       /* only double if we have had at least one add first */
+       if (first == 0) {
+          if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0)
+            goto done;
+       }
+
+       bitbuf <<= 1;
+       if ((bitbuf & (1 << WINSIZE)) != 0) {
+         if (first == 1){
+            /* first add, so copy */
+            mpz_set(R->x, tG->x);
+            mpz_set(R->y, tG->y);
+            mpz_set(R->z, tG->z);
+            first = 0;
+         } else {
+            /* then add */
+            if ((err = ecc_projective_add_point(R, tG, R, a, modulus)) != 0)
+              goto done;
+         }
+       }
+     }
+   }
+
+   /* map R back from projective space */
+   if (map) {
+      err = ecc_map(R, modulus);
+   } else {
       err = 0;
-    }
+   }
 done:
-  ecc_del_point (tG);
-  for (i = 0; i < 3; i++)
-    {
-      ecc_del_point (M[i]);
-    }
-  return err;
+   ecc_del_point(tG);
+   for (i = 0; i < 8; i++) {
+       ecc_del_point(M[i]);
+   }
+   return err;
 }
 
-/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_mulmod_timing.c,v $ */
-/* $Revision: 1.13 $ */
-/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/lib/nettle/ecc_mulmod_timing.c b/lib/nettle/ecc_mulmod_timing.c
new file mode 100644 (file)
index 0000000..349fdd8
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library 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 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* Based on public domain code of LibTomCrypt by Tom St Denis.
+ * Adapted to gmp and nettle by Nikos Mavrogiannopoulos.
+ */
+
+#include "ecc.h"
+
+/*
+  @file ecc_mulmod_timing.c
+  ECC Crypto, Tom St Denis
+*/
+
+/*
+   Perform a point multiplication  (timing resistant)
+   @param k    The scalar to multiply by
+   @param G    The base point
+   @param R    [out] Destination for kG
+   @param a        The a value of the curve
+   @param modulus  The modulus of the field the ECC curve is in
+   @param map      Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
+   @return 0 on success
+*/
+int
+ecc_mulmod_timing (mpz_t k, ecc_point * G, ecc_point * R, mpz_t a, mpz_t modulus,
+                int map)
+{
+  ecc_point *tG, *M[3];
+  int i, j, err;
+  int bit_to_read;
+  int mode;
+
+  if (k == NULL || G == NULL || R == NULL || modulus == NULL)
+    return -1;
+
+  /* alloc ram for window temps */
+  for (i = 0; i < 3; i++)
+    {
+      M[i] = ecc_new_point ();
+      if (M[i] == NULL)
+        {
+          for (j = 0; j < i; j++)
+            {
+              ecc_del_point (M[j]);
+            }
+          return -1;
+        }
+    }
+
+  /* make a copy of G incase R==G */
+  tG = ecc_new_point ();
+  if (tG == NULL)
+    {
+      err = -1;
+      goto done;
+    }
+
+  /* tG = G  and convert to montgomery */
+  mpz_set (tG->x, G->x);
+  mpz_set (tG->y, G->y);
+  mpz_set (tG->z, G->z);
+
+  /* calc the M tab */
+  /* M[0] == G */
+  mpz_set (M[0]->x, tG->x);
+  mpz_set (M[0]->y, tG->y);
+  mpz_set (M[0]->z, tG->z);
+  /* M[1] == 2G */
+  if ((err = ecc_projective_dbl_point (tG, M[1], a, modulus)) != 0)
+    {
+      goto done;
+    }
+
+  /* setup sliding window */
+  mode = 0;
+  bit_to_read = mpz_size (k) * GMP_NUMB_BITS - 1;
+
+  /* perform ops */
+  for (;;)
+    {
+      /* grab next digit as required */
+      if (bit_to_read == -1)
+        break;
+      i = mpz_tstbit (k, bit_to_read--);
+      
+      if (mode == 0 && i == 0)
+        {
+          /* dummy operations */
+          if ((err =
+               ecc_projective_add_point (M[0], M[1], M[2], a,
+                                             modulus)) != 0)
+            {
+              goto done;
+            }
+          if ((err =
+               ecc_projective_dbl_point (M[1], M[2], a, modulus)) != 0)
+            {
+              goto done;
+            }
+          continue;
+        }
+
+      if (mode == 0 && i == 1)
+        {
+          mode = 1;
+          /* dummy operations */
+          if ((err =
+               ecc_projective_add_point (M[0], M[1], M[2], a,
+                                             modulus)) != 0)
+            {
+              goto done;
+            }
+          if ((err =
+               ecc_projective_dbl_point (M[1], M[2], a, modulus)) != 0)
+            {
+              goto done;
+            }
+          continue;
+        }
+
+      if ((err =
+           ecc_projective_add_point (M[0], M[1], M[i ^ 1], a,
+                                         modulus)) != 0)
+        {
+          goto done;
+        }
+      if ((err = ecc_projective_dbl_point (M[i], M[i], a, modulus)) != 0)
+        {
+          goto done;
+        }
+    }
+
+  /* copy result out */
+  mpz_set (R->x, M[0]->x);
+  mpz_set (R->y, M[0]->y);
+  mpz_set (R->z, M[0]->z);
+
+  /* map R back from projective space */
+  if (map)
+    {
+      err = ecc_map (R, modulus);
+    }
+  else
+    {
+      err = 0;
+    }
+done:
+  ecc_del_point (tG);
+  for (i = 0; i < 3; i++)
+    {
+      ecc_del_point (M[i]);
+    }
+  return err;
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_mulmod_timing.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
index 04c3f1d0c847e8301d7cc946de3e2b79f025d3f7..674260f88f41efa5a2699001fe44e17c21b715b9 100644 (file)
@@ -72,7 +72,7 @@ ecc_sign_hash (const unsigned char *in, unsigned long inlen,
     {
       if ((err =
            ecc_make_key_ex (random_ctx, random, &pubkey, key->prime,
-                            key->order, key->A, key->B, key->Gx, key->Gy)) != 0)
+                            key->order, key->A, key->B, key->Gx, key->Gy, 1)) != 0)
         {
           goto errnokey;
         }