g10: ECDH shared point format.
authorArnaud Fontaine <arnaud.fontaine@ssi.gouv.fr>
Tue, 25 Oct 2016 11:43:08 +0000 (13:43 +0200)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 27 Oct 2016 03:16:30 +0000 (12:16 +0900)
* g10/ecdh.c (pk_ecdh_encrypt_with_shared_point): Improve handling of
ECDH shared point format.

--
This handles the case where the result comes from scdaemon.

Signed-off-by: Arnaud Fontaine <arnaud.fontaine at ssi.gouv.fr>
g10/ecdh.c

index af1d844..886427b 100644 (file)
@@ -132,14 +132,30 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
         return err;
       }
 
+    /* Expected size of the x component */
     secret_x_size = (nbits+7)/8;
-    log_assert (nbytes >= secret_x_size);
-    if ((nbytes & 1))
-      /* Remove the "04" prefix of non-compressed format.  */
-      memmove (secret_x, secret_x+1, secret_x_size);
-    if (nbytes - secret_x_size)
-      memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
 
+    if (nbytes > secret_x_size)
+      {
+        /* Uncompressed format expected, so it must start with 04 */
+        if (secret_x[0] != (byte)0x04)
+          {
+            return gpg_error (GPG_ERR_BAD_DATA);
+          }
+
+        /* Remove the "04" prefix of non-compressed format.  */
+        memmove (secret_x, secret_x+1, secret_x_size);
+
+        /* Zeroize the y component following */
+        if (nbytes > secret_x_size)
+          memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
+      }
+    else if (nbytes < secret_x_size)
+      {
+        /* Raw share secret (x coordinate), without leading zeros */
+        memmove (secret_x+(secret_x_size - nbytes), secret_x, nbytes);
+        memset (secret_x, 0, secret_x_size - nbytes);
+      }
     if (DBG_CRYPTO)
       log_printhex ("ECDH shared secret X is:", secret_x, secret_x_size );
   }
@@ -235,8 +251,8 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
         return err;
       }
     gcry_md_write(h, "\x00\x00\x00\x01", 4);      /* counter = 1 */
-    gcry_md_write(h, secret_x, secret_x_size);   /* x of the point X */
-    gcry_md_write(h, message, message_size);/* KDF parameters */
+    gcry_md_write(h, secret_x, secret_x_size);    /* x of the point X */
+    gcry_md_write(h, message, message_size);      /* KDF parameters */
 
     gcry_md_final (h);