Refactor uECC_sign() so that internally, k gan be generated in a different way. (#37)
diff --git a/uECC.c b/uECC.c
index 4166a18..955336f 100644
--- a/uECC.c
+++ b/uECC.c
@@ -69,7 +69,7 @@
     #define SUPPORTS_INT128 0
 #endif
 
-#define MAX_TRIES 16
+#define MAX_TRIES 64
 
 #if (uECC_WORD_SIZE == 1)
 
@@ -1488,17 +1488,17 @@
                                 uECC_word_t * RESTRICT Y1,
                                 uECC_word_t * RESTRICT X2,
                                 uECC_word_t * RESTRICT Y2,
-                                const uECC_word_t * RESTRICT p_initialZ) {
+                                const uECC_word_t * RESTRICT initial_Z) {
     uECC_word_t z[uECC_WORDS];
-    
+    if (initial_Z) {
+        vli_set(z, initial_Z);
+    } else {
+        vli_clear(z);
+        z[0] = 1;
+    }
+
     vli_set(X2, X1);
     vli_set(Y2, Y1);
-    
-    vli_clear(z);
-    z[0] = 1;
-    if (p_initialZ) {
-        vli_set(z, p_initialZ);
-    }
 
     apply_z(X1, Y1, z);
     EccPoint_double_jacobian(X1, Y1, z);
@@ -1744,18 +1744,24 @@
     EccPoint product;
     uECC_word_t private[uECC_WORDS];
     uECC_word_t random[uECC_WORDS];
+    uECC_word_t *initial_Z = 0;
+    uECC_word_t tries;
     
-    g_rng_function((uint8_t *)random, sizeof(random));
+    // Try to get a random initial Z value to improve protection against side-channel
+    // attacks. If the RNG fails every time (eg it was not defined), we continue so that
+    // uECC_shared_secret() can still work without an RNG defined.
+    for (tries = 0; tries < MAX_TRIES; ++tries) {
+        if (g_rng_function((uint8_t *)random, sizeof(random)) && !vli_isZero(random)) {
+            initial_Z = random;
+            break;
+        }
+    }
     
     vli_bytesToNative(private, private_key);
     vli_bytesToNative(public.x, public_key);
     vli_bytesToNative(public.y, public_key + uECC_BYTES);
     
-    EccPoint_mult(&product,
-                  &public,
-                  private,
-                  (vli_isZero(random) ? 0: random),
-                  vli_numBits(private, uECC_WORDS));
+    EccPoint_mult(&product, &public, private, initial_Z, vli_numBits(private, uECC_WORDS));
     vli_nativeToBytes(secret, product.x);
     return !EccPoint_isZero(&product);
 }
@@ -2114,67 +2120,63 @@
 }
 #endif /* (uECC_CURVE != uECC_secp160r1) */
 
-int uECC_sign(const uint8_t private_key[uECC_BYTES],
-              const uint8_t hash[uECC_BYTES],
-              uint8_t signature[uECC_BYTES*2]) {
-    uECC_word_t k[uECC_N_WORDS];
+// 0 < k < curve_n
+static int uECC_sign_with_k(const uint8_t private_key[uECC_BYTES],
+                            const uint8_t hash[uECC_BYTES],
+                            uECC_word_t k[uECC_N_WORDS],
+                            uint8_t signature[uECC_BYTES*2]) {
     uECC_word_t tmp[uECC_N_WORDS];
     uECC_word_t s[uECC_N_WORDS];
     uECC_word_t *k2[2] = {tmp, s};
     EccPoint p;
-    uECC_word_t tries = 0;
+    uECC_word_t carry;
+    uECC_word_t tries;
+
+#if (uECC_CURVE == uECC_secp160r1)
+    /* Make sure that we don't leak timing information about k.
+       See http://eprint.iacr.org/2011/232.pdf */
+    vli_add_n(tmp, k, curve_n);
+    carry = (tmp[uECC_WORDS] & 0x02);
+    vli_add_n(s, tmp, curve_n);
+
+    /* p = k * G */
+    EccPoint_mult(&p, &curve_G, k2[!carry], 0, (uECC_BYTES * 8) + 2);
+#else
+    /* Make sure that we don't leak timing information about k.
+       See http://eprint.iacr.org/2011/232.pdf */
+    carry = vli_add(tmp, k, curve_n);
+    vli_add(s, tmp, curve_n);
+
+    /* p = k * G */
+    EccPoint_mult(&p, &curve_G, k2[!carry], 0, (uECC_BYTES * 8) + 1);
+
+    /* r = x1 (mod n) */
+    if (vli_cmp(curve_n, p.x) != 1) {
+        vli_sub(p.x, p.x, curve_n);
+    }
+#endif
+    if (vli_isZero(p.x)) {
+        return 0;
+    }
     
-    do
-    {
-        uECC_word_t carry;
-    repeat:
-        if (!g_rng_function((uint8_t *)k, sizeof(k)) || (tries++ >= MAX_TRIES)) {
-            return 0;
+    // Attempt to get a random number to prevent side channel analysis of k.
+    // If the RNG fails every time (eg it was not defined), we continue so that
+    // deterministic signing can still work (with reduced security) without
+    // an RNG defined.
+    carry = 0; // use to signal that the RNG succeeded at least once.
+    for (tries = 0; tries < MAX_TRIES; ++tries) {
+        if (!g_rng_function((uint8_t *)tmp, sizeof(tmp))) {
+            continue;
         }
-        
-        if (vli_isZero(k)) {
-            goto repeat;
+        carry = 1;
+        if (!vli_isZero(tmp)) {
+            break;
         }
-        
-    #if (uECC_CURVE == uECC_secp160r1)
-        k[uECC_WORDS] &= 0x01;
-        if (vli_cmp_n(curve_n, k) != 1) {
-            goto repeat;
-        }
-        
-        /* make sure that we don't leak timing information about k. See http://eprint.iacr.org/2011/232.pdf */
-        vli_add_n(tmp, k, curve_n);
-        carry = (tmp[uECC_WORDS] & 0x02);
-        vli_add_n(s, tmp, curve_n);
-    
-        /* p = k * G */
-        EccPoint_mult(&p, &curve_G, k2[!carry], 0, (uECC_BYTES * 8) + 2);
-    #else
-        if (vli_cmp(curve_n, k) != 1) {
-            goto repeat;
-        }
-        
-        /* make sure that we don't leak timing information about k. See http://eprint.iacr.org/2011/232.pdf */
-        carry = vli_add(tmp, k, curve_n);
-        vli_add(s, tmp, curve_n);
-    
-        /* p = k * G */
-        EccPoint_mult(&p, &curve_G, k2[!carry], 0, (uECC_BYTES * 8) + 1);
-    
-        /* r = x1 (mod n) */
-        if (vli_cmp(curve_n, p.x) != 1) {
-            vli_sub(p.x, p.x, curve_n);
-        }
-    #endif
-    } while (vli_isZero(p.x));
-    
-    tries = 0;
-    do
-    {
-        if (!g_rng_function((uint8_t *)tmp, sizeof(tmp)) || (tries++ >= MAX_TRIES)) {
-            return 0;
-        }
-    } while (vli_isZero(tmp));
+    }
+    if (!carry) {
+        vli_clear(tmp);
+        tmp[0] = 1;
+    }
     
     /* Prevent side channel analysis of vli_modInv() to determine
        bits of k / the private key by premultiplying by a random number */
@@ -2195,14 +2197,41 @@
     vli_modMult_n(s, s, k); /* s = (e + r*d) / k */
 #if (uECC_CURVE == uECC_secp160r1)
     if (s[uECC_N_WORDS - 1]) {
-        goto repeat;
+        return 0;
     }
 #endif
     vli_nativeToBytes(signature + uECC_BYTES, s);
-    
     return 1;
 }
 
+int uECC_sign(const uint8_t private_key[uECC_BYTES],
+              const uint8_t hash[uECC_BYTES],
+              uint8_t signature[uECC_BYTES*2]) {
+    uECC_word_t k[uECC_N_WORDS];
+    uECC_word_t tmp[uECC_N_WORDS];
+    uECC_word_t s[uECC_N_WORDS];
+    uECC_word_t *k2[2] = {tmp, s};
+    EccPoint p;
+    uECC_word_t tries;
+    
+    for (tries = 0; tries < MAX_TRIES; ++tries) {
+        if(!g_rng_function((uint8_t *)k, sizeof(k))) {
+            return 0;
+        }
+    #if (uECC_CURVE == uECC_secp160r1)
+        k[uECC_WORDS] &= 0x01;
+    #endif
+        
+        if (vli_isZero(k) || vli_cmp_n(curve_n, k) != 1) {
+            continue;
+        }
+        if (uECC_sign_with_k(private_key, hash, k, signature)) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
 static bitcount_t smax(bitcount_t a, bitcount_t b) {
     return (a > b ? a : b);
 }
diff --git a/uECC.h b/uECC.h
index b8bdc6d..282aac3 100644
--- a/uECC.h
+++ b/uECC.h
@@ -71,6 +71,9 @@
 A correctly functioning RNG function must be set (using uECC_set_rng()) before calling
 uECC_make_key() or uECC_sign().
 
+Setting a correctly functioning RNG function improves the resistance to side-channel attacks
+for uECC_shared_secret().
+
 A correct RNG function is set by default when building for Windows, Linux, or OS X.
 If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom,
 you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined