ecc: Fix ECDH of Curve25519.
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 2 Feb 2016 04:58:48 +0000 (13:58 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 2 Feb 2016 04:58:48 +0000 (13:58 +0900)
* cipher/ecc-misc.c (_gcry_ecc_mont_decodepoint): Fix calc of NBITS
and prefix detection.
* cipher/ecc.c (ecc_generate): Use NBITS instead of CTX->NBITS.
(ecc_encrypt_raw): Use NBITS from curve instead of from P.
Fix rawmpilen calculation.
(ecc_decrypt_raw): Likewise.  Add debug output.
--

This fixes the commit dd3d06e7.  NBITS is defined 256 in ecc-curves.c,
thus, ecc_get_nbits returns 256.  But CTX->NBITS has 255 for Montgomery
curve.

cipher/ecc-misc.c
cipher/ecc.c

index 67e3b3d..33af6f7 100644 (file)
@@ -322,7 +322,9 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result)
     }
   else
     {
-      a = rawmpi = _gcry_mpi_get_buffer (pk, ctx->nbits/8, &rawmpilen, NULL);
+      unsigned int nbytes = (ctx->nbits+7)/8;
+
+      a = rawmpi = _gcry_mpi_get_buffer (pk, nbytes, &rawmpilen, NULL);
       if (!a)
         return gpg_err_code_from_syserror ();
       /*
@@ -339,16 +341,17 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result)
        * So, we need to check if it's really the prefix or not.
        * Only when it's the prefix, we remove it.
        */
-      if (ctx->nbits/8 == rawmpilen - 1)
-        rawmpi++;
-      else if (rawmpilen < ctx->nbits/8)
+      if (rawmpilen > nbytes)
+        {/* Prefix 0x40 or 0x00 */
+          rawmpi++;
+          rawmpilen = nbytes;
+        }
+      else if (rawmpilen < nbytes)
         {/*
           * It is possible for data created by older implementation
           * to have shorter length when it was parsed as MPI.
           */
-          unsigned int new_rawmpilen = ctx->nbits/8;
-
-          rawmpi = xtrymalloc (new_rawmpilen);
+          rawmpi = xtrymalloc (nbytes);
           if (!rawmpi)
             {
               gpg_err_code_t err = gpg_err_code_from_syserror ();
@@ -356,8 +359,8 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result)
               return err;
             }
 
-          memset (rawmpi, 0, new_rawmpilen - rawmpilen);
-          memcpy (rawmpi + new_rawmpilen - rawmpilen, a, rawmpilen);
+          memset (rawmpi, 0, nbytes - rawmpilen);
+          memcpy (rawmpi + nbytes - rawmpilen, a, rawmpilen);
         }
     }
 
index 105650e..7d6ad94 100644 (file)
@@ -606,8 +606,8 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
                                           &encpk, &encpklen);
       else
         {
-          encpk = _gcry_mpi_get_buffer_extra (Qx, ctx->nbits/8, -1,
-                                              &encpklen, NULL);
+          encpk = _gcry_mpi_get_buffer_extra (Qx, nbits/8,
+                                              -1, &encpklen, NULL);
           if (encpk == NULL)
             rc = gpg_err_code_from_syserror ();
           else
@@ -1231,6 +1231,7 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
 static gcry_err_code_t
 ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
 {
+  unsigned int nbits;
   gcry_err_code_t rc;
   struct pk_encoding_ctx ctx;
   gcry_sexp_t l1 = NULL;
@@ -1246,7 +1247,7 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
 
   memset (&pk, 0, sizeof pk);
   _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT,
-                                   ecc_get_nbits (keyparms));
+                                   (nbits = ecc_get_nbits (keyparms)));
 
   /* Look for flags. */
   l1 = sexp_find_token (keyparms, "flags", 0);
@@ -1371,13 +1372,13 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
       mpi_s = _gcry_ecc_ec2os (x, y, pk.E.p);
     else
       {
-        rawmpi = _gcry_mpi_get_buffer_extra (x, ec->nbits/8, -1,
-                                             &rawmpilen, NULL);
+        rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1, &rawmpilen, NULL);
         if (!rawmpi)
           rc = gpg_err_code_from_syserror ();
         else
           {
             rawmpi[0] = 0x40;
+            rawmpilen++;
             mpi_s = mpi_new (0);
             mpi_set_opaque (mpi_s, rawmpi, rawmpilen*8);
           }
@@ -1392,13 +1393,13 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
       mpi_e = _gcry_ecc_ec2os (x, y, pk.E.p);
     else
       {
-        rawmpi = _gcry_mpi_get_buffer_extra (x, ec->nbits/8, -1,
-                                             &rawmpilen, NULL);
+        rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1, &rawmpilen, NULL);
         if (!rawmpi)
           rc = gpg_err_code_from_syserror ();
         else
           {
             rawmpi[0] = 0x40;
+            rawmpilen++;
             mpi_e = mpi_new (0);
             mpi_set_opaque (mpi_e, rawmpi, rawmpilen*8);
           }
@@ -1447,6 +1448,7 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
 static gcry_err_code_t
 ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
 {
+  unsigned int nbits;
   gpg_err_code_t rc;
   struct pk_encoding_ctx ctx;
   gcry_sexp_t l1 = NULL;
@@ -1465,7 +1467,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   point_init (&R);
 
   _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
-                                   ecc_get_nbits (keyparms));
+                                   (nbits = ecc_get_nbits (keyparms)));
 
   /* Look for flags. */
   l1 = sexp_find_token (keyparms, "flags", 0);
@@ -1565,6 +1567,9 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   if (rc)
     goto leave;
 
+  if (DBG_CIPHER)
+    log_printpnt ("ecc_decrypt    kG", &kG, NULL);
+
   /* R = dkG */
   _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ec);
 
@@ -1588,7 +1593,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
         unsigned char *rawmpi;
         unsigned int rawmpilen;
 
-        rawmpi = _gcry_mpi_get_buffer_extra (x, ec->nbits/8, -1,
+        rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1,
                                              &rawmpilen, NULL);
         if (!rawmpi)
           {
@@ -1598,6 +1603,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
         else
           {
             rawmpi[0] = 0x40;
+            rawmpilen++;
             r = mpi_new (0);
             mpi_set_opaque (r, rawmpi, rawmpilen*8);
           }