CVE-2020-27209: Insufficient Information (NVD-CWE-noinfo)
value: The ECDSA operation of the micro-ecc library 1.0 is vulnerable to simple power analysis attacks which allows an adversary to extract the private ECC key.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 7.5
Published: 2021-05-20T21:15Z
Repository: https://github.com/kmackay/micro-ecc
Language: C
Files changed: uECC.c
Commit date: 2020-10-07 10:47:40 -0700
Commit message: Fix for #168

Diff: diff --git a/uECC.c b/uECC.c
index c08b7ac..17c0f6f 100644
--- a/uECC.c
+++ b/uECC.c
@@ -1208,11 +1208,11 @@ static void bits2int(uECC_word_t *native,
     uECC_vli_clear(native, num_n_words);
 #if uECC_VLI_NATIVE_LITTLE_ENDIAN
     bcopy((uint8_t *) native, bits, bits_size);
 #else
     uECC_vli_bytesToNative(native, bits, bits_size);
-#endif    
+#endif
     if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
         return;
     }
     shift = bits_size * 8 - curve->num_n_bits;
     carry = 0;
@@ -1237,10 +1237,11 @@ static int uECC_sign_with_k(const uint8_t *private_key,
                             uECC_Curve curve) {
 
     uECC_word_t tmp[uECC_MAX_WORDS];
     uECC_word_t s[uECC_MAX_WORDS];
     uECC_word_t *k2[2] = {tmp, s};
+    uECC_word_t *initial_Z = 0;
 #if uECC_VLI_NATIVE_LITTLE_ENDIAN
     uECC_word_t *p = (uECC_word_t *)signature;
 #else
     uECC_word_t p[uECC_MAX_WORDS * 2];
 #endif
@@ -1253,11 +1254,19 @@ static int uECC_sign_with_k(const uint8_t *private_key,
     if (uECC_vli_isZero(k, num_words) || uECC_vli_cmp(curve->n, k, num_n_words) != 1) {
         return 0;
     }
 
     carry = regularize_k(k, tmp, s, curve);
-    EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
+    /* If an RNG function was specified, try to get a random initial Z value to improve
+       protection against side-channel attacks. */
+    if (g_rng_function) {
+        if (!uECC_generate_random_int(k2[carry], curve->p, num_words)) {
+            return 0;
+        }
+        initial_Z = k2[carry];
+    }
+    EccPoint_mult(p, curve->G, k2[!carry], initial_Z, num_n_bits + 1, curve);
     if (uECC_vli_isZero(p, num_words)) {
         return 0;
     }
 
     /* If an RNG function was specified, get a random number
@@ -1297,11 +1306,11 @@ static int uECC_sign_with_k(const uint8_t *private_key,
     }
 #if uECC_VLI_NATIVE_LITTLE_ENDIAN
     bcopy((uint8_t *) signature + curve->num_bytes, (uint8_t *) s, curve->num_bytes);
 #else
     uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
-#endif    
+#endif
     return 1;
 }
 
 int uECC_sign(const uint8_t *private_key,
               const uint8_t *message_hash,
@@ -1470,11 +1479,11 @@ int uECC_verify(const uint8_t *public_key,
     bitcount_t i;
 #if uECC_VLI_NATIVE_LITTLE_ENDIAN
     uECC_word_t *_public = (uECC_word_t *)public_key;
 #else
     uECC_word_t _public[uECC_MAX_WORDS * 2];
-#endif    
+#endif
     uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS];
     wordcount_t num_words = curve->num_words;
     wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
 
     rx[num_n_words - 1] = 0;

Vulnerable code: #endif    
    EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
#endif    
#endif    
Fixed code: #endif
    uECC_word_t *initial_Z = 0;
    /* If an RNG function was specified, try to get a random initial Z value to improve
       protection against side-channel attacks. */
    if (g_rng_function) {
        if (!uECC_generate_random_int(k2[carry], curve->p, num_words)) {
            return 0;
        }
        initial_Z = k2[carry];
    }
    EccPoint_mult(p, curve->G, k2[!carry], initial_Z, num_n_bits + 1, curve);
#endif
#endif